mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-31 02:08:13 +00:00 
			
		
		
		
	Merge pull request #128346 from dims/update-to-latest-advisor-for-1.32
Update to latest cadvisor - `v0.51.0`
This commit is contained in:
		
							
								
								
									
										205
									
								
								LICENSES/vendor/github.com/checkpoint-restore/go-criu/v5/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										205
									
								
								LICENSES/vendor/github.com/checkpoint-restore/go-criu/v5/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,205 +0,0 @@ | ||||
| = vendor/github.com/checkpoint-restore/go-criu/v5 licensed under: = | ||||
|  | ||||
|                                  Apache License | ||||
|                            Version 2.0, January 2004 | ||||
|                         http://www.apache.org/licenses/ | ||||
|  | ||||
|    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
|  | ||||
|    1. Definitions. | ||||
|  | ||||
|       "License" shall mean the terms and conditions for use, reproduction, | ||||
|       and distribution as defined by Sections 1 through 9 of this document. | ||||
|  | ||||
|       "Licensor" shall mean the copyright owner or entity authorized by | ||||
|       the copyright owner that is granting the License. | ||||
|  | ||||
|       "Legal Entity" shall mean the union of the acting entity and all | ||||
|       other entities that control, are controlled by, or are under common | ||||
|       control with that entity. For the purposes of this definition, | ||||
|       "control" means (i) the power, direct or indirect, to cause the | ||||
|       direction or management of such entity, whether by contract or | ||||
|       otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
|       outstanding shares, or (iii) beneficial ownership of such entity. | ||||
|  | ||||
|       "You" (or "Your") shall mean an individual or Legal Entity | ||||
|       exercising permissions granted by this License. | ||||
|  | ||||
|       "Source" form shall mean the preferred form for making modifications, | ||||
|       including but not limited to software source code, documentation | ||||
|       source, and configuration files. | ||||
|  | ||||
|       "Object" form shall mean any form resulting from mechanical | ||||
|       transformation or translation of a Source form, including but | ||||
|       not limited to compiled object code, generated documentation, | ||||
|       and conversions to other media types. | ||||
|  | ||||
|       "Work" shall mean the work of authorship, whether in Source or | ||||
|       Object form, made available under the License, as indicated by a | ||||
|       copyright notice that is included in or attached to the work | ||||
|       (an example is provided in the Appendix below). | ||||
|  | ||||
|       "Derivative Works" shall mean any work, whether in Source or Object | ||||
|       form, that is based on (or derived from) the Work and for which the | ||||
|       editorial revisions, annotations, elaborations, or other modifications | ||||
|       represent, as a whole, an original work of authorship. For the purposes | ||||
|       of this License, Derivative Works shall not include works that remain | ||||
|       separable from, or merely link (or bind by name) to the interfaces of, | ||||
|       the Work and Derivative Works thereof. | ||||
|  | ||||
|       "Contribution" shall mean any work of authorship, including | ||||
|       the original version of the Work and any modifications or additions | ||||
|       to that Work or Derivative Works thereof, that is intentionally | ||||
|       submitted to Licensor for inclusion in the Work by the copyright owner | ||||
|       or by an individual or Legal Entity authorized to submit on behalf of | ||||
|       the copyright owner. For the purposes of this definition, "submitted" | ||||
|       means any form of electronic, verbal, or written communication sent | ||||
|       to the Licensor or its representatives, including but not limited to | ||||
|       communication on electronic mailing lists, source code control systems, | ||||
|       and issue tracking systems that are managed by, or on behalf of, the | ||||
|       Licensor for the purpose of discussing and improving the Work, but | ||||
|       excluding communication that is conspicuously marked or otherwise | ||||
|       designated in writing by the copyright owner as "Not a Contribution." | ||||
|  | ||||
|       "Contributor" shall mean Licensor and any individual or Legal Entity | ||||
|       on behalf of whom a Contribution has been received by Licensor and | ||||
|       subsequently incorporated within the Work. | ||||
|  | ||||
|    2. Grant of Copyright License. Subject to the terms and conditions of | ||||
|       this License, each Contributor hereby grants to You a perpetual, | ||||
|       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|       copyright license to reproduce, prepare Derivative Works of, | ||||
|       publicly display, publicly perform, sublicense, and distribute the | ||||
|       Work and such Derivative Works in Source or Object form. | ||||
|  | ||||
|    3. Grant of Patent License. Subject to the terms and conditions of | ||||
|       this License, each Contributor hereby grants to You a perpetual, | ||||
|       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|       (except as stated in this section) patent license to make, have made, | ||||
|       use, offer to sell, sell, import, and otherwise transfer the Work, | ||||
|       where such license applies only to those patent claims licensable | ||||
|       by such Contributor that are necessarily infringed by their | ||||
|       Contribution(s) alone or by combination of their Contribution(s) | ||||
|       with the Work to which such Contribution(s) was submitted. If You | ||||
|       institute patent litigation against any entity (including a | ||||
|       cross-claim or counterclaim in a lawsuit) alleging that the Work | ||||
|       or a Contribution incorporated within the Work constitutes direct | ||||
|       or contributory patent infringement, then any patent licenses | ||||
|       granted to You under this License for that Work shall terminate | ||||
|       as of the date such litigation is filed. | ||||
|  | ||||
|    4. Redistribution. You may reproduce and distribute copies of the | ||||
|       Work or Derivative Works thereof in any medium, with or without | ||||
|       modifications, and in Source or Object form, provided that You | ||||
|       meet the following conditions: | ||||
|  | ||||
|       (a) You must give any other recipients of the Work or | ||||
|           Derivative Works a copy of this License; and | ||||
|  | ||||
|       (b) You must cause any modified files to carry prominent notices | ||||
|           stating that You changed the files; and | ||||
|  | ||||
|       (c) You must retain, in the Source form of any Derivative Works | ||||
|           that You distribute, all copyright, patent, trademark, and | ||||
|           attribution notices from the Source form of the Work, | ||||
|           excluding those notices that do not pertain to any part of | ||||
|           the Derivative Works; and | ||||
|  | ||||
|       (d) If the Work includes a "NOTICE" text file as part of its | ||||
|           distribution, then any Derivative Works that You distribute must | ||||
|           include a readable copy of the attribution notices contained | ||||
|           within such NOTICE file, excluding those notices that do not | ||||
|           pertain to any part of the Derivative Works, in at least one | ||||
|           of the following places: within a NOTICE text file distributed | ||||
|           as part of the Derivative Works; within the Source form or | ||||
|           documentation, if provided along with the Derivative Works; or, | ||||
|           within a display generated by the Derivative Works, if and | ||||
|           wherever such third-party notices normally appear. The contents | ||||
|           of the NOTICE file are for informational purposes only and | ||||
|           do not modify the License. You may add Your own attribution | ||||
|           notices within Derivative Works that You distribute, alongside | ||||
|           or as an addendum to the NOTICE text from the Work, provided | ||||
|           that such additional attribution notices cannot be construed | ||||
|           as modifying the License. | ||||
|  | ||||
|       You may add Your own copyright statement to Your modifications and | ||||
|       may provide additional or different license terms and conditions | ||||
|       for use, reproduction, or distribution of Your modifications, or | ||||
|       for any such Derivative Works as a whole, provided Your use, | ||||
|       reproduction, and distribution of the Work otherwise complies with | ||||
|       the conditions stated in this License. | ||||
|  | ||||
|    5. Submission of Contributions. Unless You explicitly state otherwise, | ||||
|       any Contribution intentionally submitted for inclusion in the Work | ||||
|       by You to the Licensor shall be under the terms and conditions of | ||||
|       this License, without any additional terms or conditions. | ||||
|       Notwithstanding the above, nothing herein shall supersede or modify | ||||
|       the terms of any separate license agreement you may have executed | ||||
|       with Licensor regarding such Contributions. | ||||
|  | ||||
|    6. Trademarks. This License does not grant permission to use the trade | ||||
|       names, trademarks, service marks, or product names of the Licensor, | ||||
|       except as required for reasonable and customary use in describing the | ||||
|       origin of the Work and reproducing the content of the NOTICE file. | ||||
|  | ||||
|    7. Disclaimer of Warranty. Unless required by applicable law or | ||||
|       agreed to in writing, Licensor provides the Work (and each | ||||
|       Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
|       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||||
|       implied, including, without limitation, any warranties or conditions | ||||
|       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||||
|       PARTICULAR PURPOSE. You are solely responsible for determining the | ||||
|       appropriateness of using or redistributing the Work and assume any | ||||
|       risks associated with Your exercise of permissions under this License. | ||||
|  | ||||
|    8. Limitation of Liability. In no event and under no legal theory, | ||||
|       whether in tort (including negligence), contract, or otherwise, | ||||
|       unless required by applicable law (such as deliberate and grossly | ||||
|       negligent acts) or agreed to in writing, shall any Contributor be | ||||
|       liable to You for damages, including any direct, indirect, special, | ||||
|       incidental, or consequential damages of any character arising as a | ||||
|       result of this License or out of the use or inability to use the | ||||
|       Work (including but not limited to damages for loss of goodwill, | ||||
|       work stoppage, computer failure or malfunction, or any and all | ||||
|       other commercial damages or losses), even if such Contributor | ||||
|       has been advised of the possibility of such damages. | ||||
|  | ||||
|    9. Accepting Warranty or Additional Liability. While redistributing | ||||
|       the Work or Derivative Works thereof, You may choose to offer, | ||||
|       and charge a fee for, acceptance of support, warranty, indemnity, | ||||
|       or other liability obligations and/or rights consistent with this | ||||
|       License. However, in accepting such obligations, You may act only | ||||
|       on Your own behalf and on Your sole responsibility, not on behalf | ||||
|       of any other Contributor, and only if You agree to indemnify, | ||||
|       defend, and hold each Contributor harmless for any liability | ||||
|       incurred by, or claims asserted against, such Contributor by reason | ||||
|       of your accepting any such warranty or additional liability. | ||||
|  | ||||
|    END OF TERMS AND CONDITIONS | ||||
|  | ||||
|    APPENDIX: How to apply the Apache License to your work. | ||||
|  | ||||
|       To apply the Apache License to your work, attach the following | ||||
|       boilerplate notice, with the fields enclosed by brackets "{}" | ||||
|       replaced with your own identifying information. (Don't include | ||||
|       the brackets!)  The text should be enclosed in the appropriate | ||||
|       comment syntax for the file format. We also recommend that a | ||||
|       file or class name and description of purpose be included on the | ||||
|       same "printed page" as the copyright notice for easier | ||||
|       identification within third-party archives. | ||||
|  | ||||
|    Copyright {yyyy} {name of copyright owner} | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
|  | ||||
| = vendor/github.com/checkpoint-restore/go-criu/v5/LICENSE e3fc50a88d0a364313df4b21ef20c29e | ||||
							
								
								
									
										195
									
								
								LICENSES/vendor/github.com/containerd/console/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										195
									
								
								LICENSES/vendor/github.com/containerd/console/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,195 +0,0 @@ | ||||
| = vendor/github.com/containerd/console licensed under: = | ||||
|  | ||||
|  | ||||
|                                  Apache License | ||||
|                            Version 2.0, January 2004 | ||||
|                         https://www.apache.org/licenses/ | ||||
|  | ||||
|    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
|  | ||||
|    1. Definitions. | ||||
|  | ||||
|       "License" shall mean the terms and conditions for use, reproduction, | ||||
|       and distribution as defined by Sections 1 through 9 of this document. | ||||
|  | ||||
|       "Licensor" shall mean the copyright owner or entity authorized by | ||||
|       the copyright owner that is granting the License. | ||||
|  | ||||
|       "Legal Entity" shall mean the union of the acting entity and all | ||||
|       other entities that control, are controlled by, or are under common | ||||
|       control with that entity. For the purposes of this definition, | ||||
|       "control" means (i) the power, direct or indirect, to cause the | ||||
|       direction or management of such entity, whether by contract or | ||||
|       otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
|       outstanding shares, or (iii) beneficial ownership of such entity. | ||||
|  | ||||
|       "You" (or "Your") shall mean an individual or Legal Entity | ||||
|       exercising permissions granted by this License. | ||||
|  | ||||
|       "Source" form shall mean the preferred form for making modifications, | ||||
|       including but not limited to software source code, documentation | ||||
|       source, and configuration files. | ||||
|  | ||||
|       "Object" form shall mean any form resulting from mechanical | ||||
|       transformation or translation of a Source form, including but | ||||
|       not limited to compiled object code, generated documentation, | ||||
|       and conversions to other media types. | ||||
|  | ||||
|       "Work" shall mean the work of authorship, whether in Source or | ||||
|       Object form, made available under the License, as indicated by a | ||||
|       copyright notice that is included in or attached to the work | ||||
|       (an example is provided in the Appendix below). | ||||
|  | ||||
|       "Derivative Works" shall mean any work, whether in Source or Object | ||||
|       form, that is based on (or derived from) the Work and for which the | ||||
|       editorial revisions, annotations, elaborations, or other modifications | ||||
|       represent, as a whole, an original work of authorship. For the purposes | ||||
|       of this License, Derivative Works shall not include works that remain | ||||
|       separable from, or merely link (or bind by name) to the interfaces of, | ||||
|       the Work and Derivative Works thereof. | ||||
|  | ||||
|       "Contribution" shall mean any work of authorship, including | ||||
|       the original version of the Work and any modifications or additions | ||||
|       to that Work or Derivative Works thereof, that is intentionally | ||||
|       submitted to Licensor for inclusion in the Work by the copyright owner | ||||
|       or by an individual or Legal Entity authorized to submit on behalf of | ||||
|       the copyright owner. For the purposes of this definition, "submitted" | ||||
|       means any form of electronic, verbal, or written communication sent | ||||
|       to the Licensor or its representatives, including but not limited to | ||||
|       communication on electronic mailing lists, source code control systems, | ||||
|       and issue tracking systems that are managed by, or on behalf of, the | ||||
|       Licensor for the purpose of discussing and improving the Work, but | ||||
|       excluding communication that is conspicuously marked or otherwise | ||||
|       designated in writing by the copyright owner as "Not a Contribution." | ||||
|  | ||||
|       "Contributor" shall mean Licensor and any individual or Legal Entity | ||||
|       on behalf of whom a Contribution has been received by Licensor and | ||||
|       subsequently incorporated within the Work. | ||||
|  | ||||
|    2. Grant of Copyright License. Subject to the terms and conditions of | ||||
|       this License, each Contributor hereby grants to You a perpetual, | ||||
|       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|       copyright license to reproduce, prepare Derivative Works of, | ||||
|       publicly display, publicly perform, sublicense, and distribute the | ||||
|       Work and such Derivative Works in Source or Object form. | ||||
|  | ||||
|    3. Grant of Patent License. Subject to the terms and conditions of | ||||
|       this License, each Contributor hereby grants to You a perpetual, | ||||
|       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|       (except as stated in this section) patent license to make, have made, | ||||
|       use, offer to sell, sell, import, and otherwise transfer the Work, | ||||
|       where such license applies only to those patent claims licensable | ||||
|       by such Contributor that are necessarily infringed by their | ||||
|       Contribution(s) alone or by combination of their Contribution(s) | ||||
|       with the Work to which such Contribution(s) was submitted. If You | ||||
|       institute patent litigation against any entity (including a | ||||
|       cross-claim or counterclaim in a lawsuit) alleging that the Work | ||||
|       or a Contribution incorporated within the Work constitutes direct | ||||
|       or contributory patent infringement, then any patent licenses | ||||
|       granted to You under this License for that Work shall terminate | ||||
|       as of the date such litigation is filed. | ||||
|  | ||||
|    4. Redistribution. You may reproduce and distribute copies of the | ||||
|       Work or Derivative Works thereof in any medium, with or without | ||||
|       modifications, and in Source or Object form, provided that You | ||||
|       meet the following conditions: | ||||
|  | ||||
|       (a) You must give any other recipients of the Work or | ||||
|           Derivative Works a copy of this License; and | ||||
|  | ||||
|       (b) You must cause any modified files to carry prominent notices | ||||
|           stating that You changed the files; and | ||||
|  | ||||
|       (c) You must retain, in the Source form of any Derivative Works | ||||
|           that You distribute, all copyright, patent, trademark, and | ||||
|           attribution notices from the Source form of the Work, | ||||
|           excluding those notices that do not pertain to any part of | ||||
|           the Derivative Works; and | ||||
|  | ||||
|       (d) If the Work includes a "NOTICE" text file as part of its | ||||
|           distribution, then any Derivative Works that You distribute must | ||||
|           include a readable copy of the attribution notices contained | ||||
|           within such NOTICE file, excluding those notices that do not | ||||
|           pertain to any part of the Derivative Works, in at least one | ||||
|           of the following places: within a NOTICE text file distributed | ||||
|           as part of the Derivative Works; within the Source form or | ||||
|           documentation, if provided along with the Derivative Works; or, | ||||
|           within a display generated by the Derivative Works, if and | ||||
|           wherever such third-party notices normally appear. The contents | ||||
|           of the NOTICE file are for informational purposes only and | ||||
|           do not modify the License. You may add Your own attribution | ||||
|           notices within Derivative Works that You distribute, alongside | ||||
|           or as an addendum to the NOTICE text from the Work, provided | ||||
|           that such additional attribution notices cannot be construed | ||||
|           as modifying the License. | ||||
|  | ||||
|       You may add Your own copyright statement to Your modifications and | ||||
|       may provide additional or different license terms and conditions | ||||
|       for use, reproduction, or distribution of Your modifications, or | ||||
|       for any such Derivative Works as a whole, provided Your use, | ||||
|       reproduction, and distribution of the Work otherwise complies with | ||||
|       the conditions stated in this License. | ||||
|  | ||||
|    5. Submission of Contributions. Unless You explicitly state otherwise, | ||||
|       any Contribution intentionally submitted for inclusion in the Work | ||||
|       by You to the Licensor shall be under the terms and conditions of | ||||
|       this License, without any additional terms or conditions. | ||||
|       Notwithstanding the above, nothing herein shall supersede or modify | ||||
|       the terms of any separate license agreement you may have executed | ||||
|       with Licensor regarding such Contributions. | ||||
|  | ||||
|    6. Trademarks. This License does not grant permission to use the trade | ||||
|       names, trademarks, service marks, or product names of the Licensor, | ||||
|       except as required for reasonable and customary use in describing the | ||||
|       origin of the Work and reproducing the content of the NOTICE file. | ||||
|  | ||||
|    7. Disclaimer of Warranty. Unless required by applicable law or | ||||
|       agreed to in writing, Licensor provides the Work (and each | ||||
|       Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
|       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||||
|       implied, including, without limitation, any warranties or conditions | ||||
|       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||||
|       PARTICULAR PURPOSE. You are solely responsible for determining the | ||||
|       appropriateness of using or redistributing the Work and assume any | ||||
|       risks associated with Your exercise of permissions under this License. | ||||
|  | ||||
|    8. Limitation of Liability. In no event and under no legal theory, | ||||
|       whether in tort (including negligence), contract, or otherwise, | ||||
|       unless required by applicable law (such as deliberate and grossly | ||||
|       negligent acts) or agreed to in writing, shall any Contributor be | ||||
|       liable to You for damages, including any direct, indirect, special, | ||||
|       incidental, or consequential damages of any character arising as a | ||||
|       result of this License or out of the use or inability to use the | ||||
|       Work (including but not limited to damages for loss of goodwill, | ||||
|       work stoppage, computer failure or malfunction, or any and all | ||||
|       other commercial damages or losses), even if such Contributor | ||||
|       has been advised of the possibility of such damages. | ||||
|  | ||||
|    9. Accepting Warranty or Additional Liability. While redistributing | ||||
|       the Work or Derivative Works thereof, You may choose to offer, | ||||
|       and charge a fee for, acceptance of support, warranty, indemnity, | ||||
|       or other liability obligations and/or rights consistent with this | ||||
|       License. However, in accepting such obligations, You may act only | ||||
|       on Your own behalf and on Your sole responsibility, not on behalf | ||||
|       of any other Contributor, and only if You agree to indemnify, | ||||
|       defend, and hold each Contributor harmless for any liability | ||||
|       incurred by, or claims asserted against, such Contributor by reason | ||||
|       of your accepting any such warranty or additional liability. | ||||
|  | ||||
|    END OF TERMS AND CONDITIONS | ||||
|  | ||||
|    Copyright The containerd Authors | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        https://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
|  | ||||
| = vendor/github.com/containerd/console/LICENSE 1269f40c0d099c21a871163984590d89 | ||||
							
								
								
									
										26
									
								
								LICENSES/vendor/github.com/seccomp/libseccomp-golang/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								LICENSES/vendor/github.com/seccomp/libseccomp-golang/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,26 +0,0 @@ | ||||
| = vendor/github.com/seccomp/libseccomp-golang licensed under: = | ||||
|  | ||||
| Copyright (c) 2015 Matthew Heon <mheon@redhat.com> | ||||
| Copyright (c) 2015 Paul Moore <pmoore@redhat.com> | ||||
| All rights reserved. | ||||
|  | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions are met: | ||||
| - Redistributions of source code must retain the above copyright notice, | ||||
|   this list of conditions and the following disclaimer. | ||||
| - Redistributions in binary form must reproduce the above copyright notice, | ||||
|   this list of conditions and the following disclaimer in the documentation | ||||
|   and/or other materials provided with the distribution. | ||||
|  | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||||
| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||
| FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||
| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||
| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||
| OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  | ||||
| = vendor/github.com/seccomp/libseccomp-golang/LICENSE 343b433e752e8b44a543cdf61f14b628 | ||||
							
								
								
									
										28
									
								
								LICENSES/vendor/github.com/syndtr/gocapability/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								LICENSES/vendor/github.com/syndtr/gocapability/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,28 +0,0 @@ | ||||
| = vendor/github.com/syndtr/gocapability licensed under: = | ||||
|  | ||||
| Copyright 2013 Suryandaru Triandana <syndtr@gmail.com> | ||||
| All rights reserved. | ||||
|  | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions are | ||||
| met: | ||||
|  | ||||
|     * Redistributions of source code must retain the above copyright | ||||
| notice, this list of conditions and the following disclaimer. | ||||
|     * Redistributions in binary form must reproduce the above copyright | ||||
| notice, this list of conditions and the following disclaimer in the | ||||
| documentation and/or other materials provided with the distribution. | ||||
|  | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
| HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||
| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  | ||||
| = vendor/github.com/syndtr/gocapability/LICENSE a7304f5073e7be4ba7bffabbf9f2bbca | ||||
							
								
								
									
										5
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								go.mod
									
									
									
									
									
								
							| @@ -34,7 +34,7 @@ require ( | ||||
| 	github.com/gogo/protobuf v1.3.2 | ||||
| 	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da | ||||
| 	github.com/golang/protobuf v1.5.4 | ||||
| 	github.com/google/cadvisor v0.50.0 | ||||
| 	github.com/google/cadvisor v0.51.0 | ||||
| 	github.com/google/cel-go v0.21.0 | ||||
| 	github.com/google/gnostic-models v0.6.8 | ||||
| 	github.com/google/go-cmp v0.6.0 | ||||
| @@ -134,9 +134,7 @@ require ( | ||||
| 	github.com/cenkalti/backoff/v4 v4.3.0 // indirect | ||||
| 	github.com/cespare/xxhash/v2 v2.3.0 // indirect | ||||
| 	github.com/chai2010/gettext-go v1.0.2 // indirect | ||||
| 	github.com/checkpoint-restore/go-criu/v5 v5.3.0 // indirect | ||||
| 	github.com/cilium/ebpf v0.11.0 // indirect | ||||
| 	github.com/containerd/console v1.0.4 // indirect | ||||
| 	github.com/containerd/containerd/api v1.7.19 // indirect | ||||
| 	github.com/containerd/errdefs v0.1.0 // indirect | ||||
| 	github.com/containerd/log v0.1.0 // indirect | ||||
| @@ -196,7 +194,6 @@ require ( | ||||
| 	github.com/soheilhy/cmux v0.1.5 // indirect | ||||
| 	github.com/stoewer/go-strcase v1.3.0 // indirect | ||||
| 	github.com/stretchr/objx v0.5.2 // indirect | ||||
| 	github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect | ||||
| 	github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 // indirect | ||||
| 	github.com/x448/float16 v0.8.4 // indirect | ||||
| 	github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 // indirect | ||||
|   | ||||
							
								
								
									
										15
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								go.sum
									
									
									
									
									
								
							| @@ -169,7 +169,6 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF | ||||
| github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= | ||||
| github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= | ||||
| github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= | ||||
| github.com/checkpoint-restore/go-criu/v5 v5.3.0 h1:wpFFOoomK3389ue2lAb0Boag6XPht5QYpipxmSNL4d8= | ||||
| github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= | ||||
| github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= | ||||
| github.com/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y= | ||||
| @@ -183,8 +182,7 @@ github.com/container-storage-interface/spec v1.9.0 h1:zKtX4STsq31Knz3gciCYCi1SXt | ||||
| github.com/container-storage-interface/spec v1.9.0/go.mod h1:ZfDu+3ZRyeVqxZM0Ds19MVLkN2d1XJ5MAfi1L3VjlT0= | ||||
| github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= | ||||
| github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= | ||||
| github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= | ||||
| github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= | ||||
| github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= | ||||
| github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA= | ||||
| github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig= | ||||
| github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM= | ||||
| @@ -299,7 +297,6 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W | ||||
| github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= | ||||
| github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= | ||||
| github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= | ||||
| github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= | ||||
| github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= | ||||
| github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= | ||||
| github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho= | ||||
| @@ -309,8 +306,8 @@ github.com/golangplus/testing v1.0.0 h1:+ZeeiKZENNOMkTTELoSySazi+XaEhVO0mb+eanrS | ||||
| github.com/golangplus/testing v1.0.0/go.mod h1:ZDreixUV3YzhoVraIDyOzHrr76p6NUh6k/pPg/Q3gYA= | ||||
| github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= | ||||
| github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= | ||||
| github.com/google/cadvisor v0.50.0 h1:7w/hKIbJKBWqQsRTy+Hpj2vj+fnxrLXcEXFy+LW0Bsg= | ||||
| github.com/google/cadvisor v0.50.0/go.mod h1:VxCDwZalpFyENvmfabFqaIGsqNKLtDzE62a19rfVTB8= | ||||
| github.com/google/cadvisor v0.51.0 h1:BspqSPdZoLKrnvuZNOvM/KiJ/A+RdixwagN20n+2H8k= | ||||
| github.com/google/cadvisor v0.51.0/go.mod h1:czGE/c/P/i0QFpVNKTFrIEzord9Y10YfpwuaSWXELc0= | ||||
| github.com/google/cel-go v0.21.0 h1:cl6uW/gxN+Hy50tNYvI691+sXxioCnstFzLp2WO4GCI= | ||||
| github.com/google/cel-go v0.21.0/go.mod h1:rHUlWCcBKgyEk+eV03RPdZUekPp6YcJwV0FxuUksYxc= | ||||
| github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= | ||||
| @@ -321,7 +318,6 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw | ||||
| github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
| github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
| github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
| github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
| github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= | ||||
| github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= | ||||
| github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= | ||||
| @@ -492,7 +488,6 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO | ||||
| github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= | ||||
| github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= | ||||
| github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||||
| github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= | ||||
| github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= | ||||
| github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= | ||||
| github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= | ||||
| @@ -614,12 +609,10 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w | ||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= | ||||
| @@ -681,8 +674,6 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 | ||||
| google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | ||||
| google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | ||||
| google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= | ||||
| google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= | ||||
| google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= | ||||
| google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= | ||||
| google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
|   | ||||
| @@ -134,10 +134,12 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.2 h1:ORnrOK0C4WmYV/uYt3koHEWB | ||||
| github.com/aws/aws-sdk-go-v2/service/sts v1.30.1 h1:+woJ607dllHJQtsnJLi52ycuqHMwlW+Wqm2Ppsfp4nQ= | ||||
| github.com/aws/smithy-go v1.20.3 h1:ryHwveWzPV5BIof6fyDvor6V3iUL7nTfiTKXHiW05nE= | ||||
| github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= | ||||
| github.com/checkpoint-restore/go-criu/v5 v5.3.0 h1:wpFFOoomK3389ue2lAb0Boag6XPht5QYpipxmSNL4d8= | ||||
| github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= | ||||
| github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= | ||||
| github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f h1:WBZRG4aNOuI15bLRrCgN8fCq8E5Xuty6jGbmSNEvSsU= | ||||
| github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= | ||||
| github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= | ||||
| github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= | ||||
| github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= | ||||
| github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= | ||||
| @@ -165,6 +167,7 @@ github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsq | ||||
| github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= | ||||
| github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= | ||||
| github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= | ||||
| github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= | ||||
| github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= | ||||
| github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= | ||||
| github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= | ||||
|   | ||||
							
								
								
									
										6
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,6 +0,0 @@ | ||||
| test/test | ||||
| test/test.coverage | ||||
| test/piggie/piggie | ||||
| test/phaul/phaul | ||||
| test/phaul/phaul.coverage | ||||
| image | ||||
							
								
								
									
										12
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/.golangci.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/.golangci.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,12 +0,0 @@ | ||||
| run: | ||||
|   skip_dirs: | ||||
|     - rpc | ||||
|     - stats | ||||
|  | ||||
| linters: | ||||
|   disable-all: false | ||||
|   presets: | ||||
|     - bugs | ||||
|     - performance | ||||
|     - unused | ||||
|     - format | ||||
							
								
								
									
										201
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										201
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,201 +0,0 @@ | ||||
|                                  Apache License | ||||
|                            Version 2.0, January 2004 | ||||
|                         http://www.apache.org/licenses/ | ||||
|  | ||||
|    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
|  | ||||
|    1. Definitions. | ||||
|  | ||||
|       "License" shall mean the terms and conditions for use, reproduction, | ||||
|       and distribution as defined by Sections 1 through 9 of this document. | ||||
|  | ||||
|       "Licensor" shall mean the copyright owner or entity authorized by | ||||
|       the copyright owner that is granting the License. | ||||
|  | ||||
|       "Legal Entity" shall mean the union of the acting entity and all | ||||
|       other entities that control, are controlled by, or are under common | ||||
|       control with that entity. For the purposes of this definition, | ||||
|       "control" means (i) the power, direct or indirect, to cause the | ||||
|       direction or management of such entity, whether by contract or | ||||
|       otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
|       outstanding shares, or (iii) beneficial ownership of such entity. | ||||
|  | ||||
|       "You" (or "Your") shall mean an individual or Legal Entity | ||||
|       exercising permissions granted by this License. | ||||
|  | ||||
|       "Source" form shall mean the preferred form for making modifications, | ||||
|       including but not limited to software source code, documentation | ||||
|       source, and configuration files. | ||||
|  | ||||
|       "Object" form shall mean any form resulting from mechanical | ||||
|       transformation or translation of a Source form, including but | ||||
|       not limited to compiled object code, generated documentation, | ||||
|       and conversions to other media types. | ||||
|  | ||||
|       "Work" shall mean the work of authorship, whether in Source or | ||||
|       Object form, made available under the License, as indicated by a | ||||
|       copyright notice that is included in or attached to the work | ||||
|       (an example is provided in the Appendix below). | ||||
|  | ||||
|       "Derivative Works" shall mean any work, whether in Source or Object | ||||
|       form, that is based on (or derived from) the Work and for which the | ||||
|       editorial revisions, annotations, elaborations, or other modifications | ||||
|       represent, as a whole, an original work of authorship. For the purposes | ||||
|       of this License, Derivative Works shall not include works that remain | ||||
|       separable from, or merely link (or bind by name) to the interfaces of, | ||||
|       the Work and Derivative Works thereof. | ||||
|  | ||||
|       "Contribution" shall mean any work of authorship, including | ||||
|       the original version of the Work and any modifications or additions | ||||
|       to that Work or Derivative Works thereof, that is intentionally | ||||
|       submitted to Licensor for inclusion in the Work by the copyright owner | ||||
|       or by an individual or Legal Entity authorized to submit on behalf of | ||||
|       the copyright owner. For the purposes of this definition, "submitted" | ||||
|       means any form of electronic, verbal, or written communication sent | ||||
|       to the Licensor or its representatives, including but not limited to | ||||
|       communication on electronic mailing lists, source code control systems, | ||||
|       and issue tracking systems that are managed by, or on behalf of, the | ||||
|       Licensor for the purpose of discussing and improving the Work, but | ||||
|       excluding communication that is conspicuously marked or otherwise | ||||
|       designated in writing by the copyright owner as "Not a Contribution." | ||||
|  | ||||
|       "Contributor" shall mean Licensor and any individual or Legal Entity | ||||
|       on behalf of whom a Contribution has been received by Licensor and | ||||
|       subsequently incorporated within the Work. | ||||
|  | ||||
|    2. Grant of Copyright License. Subject to the terms and conditions of | ||||
|       this License, each Contributor hereby grants to You a perpetual, | ||||
|       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|       copyright license to reproduce, prepare Derivative Works of, | ||||
|       publicly display, publicly perform, sublicense, and distribute the | ||||
|       Work and such Derivative Works in Source or Object form. | ||||
|  | ||||
|    3. Grant of Patent License. Subject to the terms and conditions of | ||||
|       this License, each Contributor hereby grants to You a perpetual, | ||||
|       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|       (except as stated in this section) patent license to make, have made, | ||||
|       use, offer to sell, sell, import, and otherwise transfer the Work, | ||||
|       where such license applies only to those patent claims licensable | ||||
|       by such Contributor that are necessarily infringed by their | ||||
|       Contribution(s) alone or by combination of their Contribution(s) | ||||
|       with the Work to which such Contribution(s) was submitted. If You | ||||
|       institute patent litigation against any entity (including a | ||||
|       cross-claim or counterclaim in a lawsuit) alleging that the Work | ||||
|       or a Contribution incorporated within the Work constitutes direct | ||||
|       or contributory patent infringement, then any patent licenses | ||||
|       granted to You under this License for that Work shall terminate | ||||
|       as of the date such litigation is filed. | ||||
|  | ||||
|    4. Redistribution. You may reproduce and distribute copies of the | ||||
|       Work or Derivative Works thereof in any medium, with or without | ||||
|       modifications, and in Source or Object form, provided that You | ||||
|       meet the following conditions: | ||||
|  | ||||
|       (a) You must give any other recipients of the Work or | ||||
|           Derivative Works a copy of this License; and | ||||
|  | ||||
|       (b) You must cause any modified files to carry prominent notices | ||||
|           stating that You changed the files; and | ||||
|  | ||||
|       (c) You must retain, in the Source form of any Derivative Works | ||||
|           that You distribute, all copyright, patent, trademark, and | ||||
|           attribution notices from the Source form of the Work, | ||||
|           excluding those notices that do not pertain to any part of | ||||
|           the Derivative Works; and | ||||
|  | ||||
|       (d) If the Work includes a "NOTICE" text file as part of its | ||||
|           distribution, then any Derivative Works that You distribute must | ||||
|           include a readable copy of the attribution notices contained | ||||
|           within such NOTICE file, excluding those notices that do not | ||||
|           pertain to any part of the Derivative Works, in at least one | ||||
|           of the following places: within a NOTICE text file distributed | ||||
|           as part of the Derivative Works; within the Source form or | ||||
|           documentation, if provided along with the Derivative Works; or, | ||||
|           within a display generated by the Derivative Works, if and | ||||
|           wherever such third-party notices normally appear. The contents | ||||
|           of the NOTICE file are for informational purposes only and | ||||
|           do not modify the License. You may add Your own attribution | ||||
|           notices within Derivative Works that You distribute, alongside | ||||
|           or as an addendum to the NOTICE text from the Work, provided | ||||
|           that such additional attribution notices cannot be construed | ||||
|           as modifying the License. | ||||
|  | ||||
|       You may add Your own copyright statement to Your modifications and | ||||
|       may provide additional or different license terms and conditions | ||||
|       for use, reproduction, or distribution of Your modifications, or | ||||
|       for any such Derivative Works as a whole, provided Your use, | ||||
|       reproduction, and distribution of the Work otherwise complies with | ||||
|       the conditions stated in this License. | ||||
|  | ||||
|    5. Submission of Contributions. Unless You explicitly state otherwise, | ||||
|       any Contribution intentionally submitted for inclusion in the Work | ||||
|       by You to the Licensor shall be under the terms and conditions of | ||||
|       this License, without any additional terms or conditions. | ||||
|       Notwithstanding the above, nothing herein shall supersede or modify | ||||
|       the terms of any separate license agreement you may have executed | ||||
|       with Licensor regarding such Contributions. | ||||
|  | ||||
|    6. Trademarks. This License does not grant permission to use the trade | ||||
|       names, trademarks, service marks, or product names of the Licensor, | ||||
|       except as required for reasonable and customary use in describing the | ||||
|       origin of the Work and reproducing the content of the NOTICE file. | ||||
|  | ||||
|    7. Disclaimer of Warranty. Unless required by applicable law or | ||||
|       agreed to in writing, Licensor provides the Work (and each | ||||
|       Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
|       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||||
|       implied, including, without limitation, any warranties or conditions | ||||
|       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||||
|       PARTICULAR PURPOSE. You are solely responsible for determining the | ||||
|       appropriateness of using or redistributing the Work and assume any | ||||
|       risks associated with Your exercise of permissions under this License. | ||||
|  | ||||
|    8. Limitation of Liability. In no event and under no legal theory, | ||||
|       whether in tort (including negligence), contract, or otherwise, | ||||
|       unless required by applicable law (such as deliberate and grossly | ||||
|       negligent acts) or agreed to in writing, shall any Contributor be | ||||
|       liable to You for damages, including any direct, indirect, special, | ||||
|       incidental, or consequential damages of any character arising as a | ||||
|       result of this License or out of the use or inability to use the | ||||
|       Work (including but not limited to damages for loss of goodwill, | ||||
|       work stoppage, computer failure or malfunction, or any and all | ||||
|       other commercial damages or losses), even if such Contributor | ||||
|       has been advised of the possibility of such damages. | ||||
|  | ||||
|    9. Accepting Warranty or Additional Liability. While redistributing | ||||
|       the Work or Derivative Works thereof, You may choose to offer, | ||||
|       and charge a fee for, acceptance of support, warranty, indemnity, | ||||
|       or other liability obligations and/or rights consistent with this | ||||
|       License. However, in accepting such obligations, You may act only | ||||
|       on Your own behalf and on Your sole responsibility, not on behalf | ||||
|       of any other Contributor, and only if You agree to indemnify, | ||||
|       defend, and hold each Contributor harmless for any liability | ||||
|       incurred by, or claims asserted against, such Contributor by reason | ||||
|       of your accepting any such warranty or additional liability. | ||||
|  | ||||
|    END OF TERMS AND CONDITIONS | ||||
|  | ||||
|    APPENDIX: How to apply the Apache License to your work. | ||||
|  | ||||
|       To apply the Apache License to your work, attach the following | ||||
|       boilerplate notice, with the fields enclosed by brackets "{}" | ||||
|       replaced with your own identifying information. (Don't include | ||||
|       the brackets!)  The text should be enclosed in the appropriate | ||||
|       comment syntax for the file format. We also recommend that a | ||||
|       file or class name and description of purpose be included on the | ||||
|       same "printed page" as the copyright notice for easier | ||||
|       identification within third-party archives. | ||||
|  | ||||
|    Copyright {yyyy} {name of copyright owner} | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
							
								
								
									
										107
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/Makefile
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										107
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/Makefile
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,107 +0,0 @@ | ||||
| SHELL = /bin/bash | ||||
| GO ?= go | ||||
| CC ?= gcc | ||||
| COVERAGE_PATH ?= $(shell pwd)/.coverage | ||||
| CRIU_FEATURE_MEM_TRACK = $(shell if criu check --feature mem_dirty_track > /dev/null; then echo 1; else echo 0; fi) | ||||
| CRIU_FEATURE_LAZY_PAGES = $(shell if criu check --feature uffd-noncoop > /dev/null; then echo 1; else echo 0; fi) | ||||
| CRIU_FEATURE_PIDFD_STORE = $(shell if criu check --feature pidfd_store > /dev/null; then echo 1; else echo 0; fi) | ||||
|  | ||||
| export CRIU_FEATURE_MEM_TRACK CRIU_FEATURE_LAZY_PAGES CRIU_FEATURE_PIDFD_STORE | ||||
|  | ||||
| all: build test phaul-test | ||||
|  | ||||
| lint: | ||||
| 	golangci-lint run ./... | ||||
|  | ||||
| build: | ||||
| 	$(GO) build -v ./... | ||||
|  | ||||
| TEST_PAYLOAD := test/piggie/piggie | ||||
| TEST_BINARIES := test/test $(TEST_PAYLOAD) test/phaul/phaul | ||||
| COVERAGE_BINARIES := test/test.coverage test/phaul/phaul.coverage | ||||
| test-bin: $(TEST_BINARIES) | ||||
|  | ||||
| test/piggie/piggie: test/piggie/piggie.c | ||||
| 	$(CC) $^ -o $@ | ||||
|  | ||||
| test/test: test/main.go | ||||
| 	$(GO) build -v -o $@ $^ | ||||
|  | ||||
| test: $(TEST_BINARIES) | ||||
| 	mkdir -p image | ||||
| 	PID=$$(test/piggie/piggie) && { \ | ||||
| 	test/test dump $$PID image && \ | ||||
| 	test/test restore image; \ | ||||
| 	pkill -9 piggie; \ | ||||
| 	} | ||||
| 	rm -rf image | ||||
|  | ||||
| test/phaul/phaul: test/phaul/main.go | ||||
| 	$(GO) build -v -o $@ $^ | ||||
|  | ||||
| phaul-test: $(TEST_BINARIES) | ||||
| 	rm -rf image | ||||
| 	PID=$$(test/piggie/piggie) && { \ | ||||
| 	test/phaul/phaul $$PID; \ | ||||
| 	pkill -9 piggie; \ | ||||
| 	} | ||||
|  | ||||
| test/test.coverage: test/*.go | ||||
| 	$(GO) test \ | ||||
| 		-covermode=count \ | ||||
| 		-coverpkg=./... \ | ||||
| 		-mod=vendor \ | ||||
| 		-tags coverage \ | ||||
| 		-buildmode=pie -c -o $@ $^ | ||||
|  | ||||
| test/phaul/phaul.coverage: test/phaul/*.go | ||||
| 	$(GO) test \ | ||||
| 		-covermode=count \ | ||||
| 		-coverpkg=./... \ | ||||
| 		-mod=vendor \ | ||||
| 		-tags coverage \ | ||||
| 		-buildmode=pie -c -o $@ $^ | ||||
|  | ||||
| coverage: $(COVERAGE_BINARIES) $(TEST_PAYLOAD) | ||||
| 	mkdir -p $(COVERAGE_PATH) | ||||
| 	mkdir -p image | ||||
| 	PID=$$(test/piggie/piggie) && { \ | ||||
| 	test/test.coverage -test.coverprofile=coverprofile.integration.$$RANDOM -test.outputdir=${COVERAGE_PATH} COVERAGE dump $$PID image && \ | ||||
| 	test/test.coverage -test.coverprofile=coverprofile.integration.$$RANDOM -test.outputdir=${COVERAGE_PATH} COVERAGE restore image; \ | ||||
| 	pkill -9 piggie; \ | ||||
| 	} | ||||
| 	rm -rf image | ||||
| 	PID=$$(test/piggie/piggie) && { \ | ||||
| 	test/phaul/phaul.coverage -test.coverprofile=coverprofile.integration.$$RANDOM -test.outputdir=${COVERAGE_PATH} COVERAGE $$PID; \ | ||||
| 	pkill -9 piggie; \ | ||||
| 	} | ||||
| 	echo "mode: set" > .coverage/coverage.out && cat .coverage/coverprofile* | \ | ||||
| 		grep -v mode: | sort -r | awk '{if($$1 != last) {print $$0;last=$$1}}' >> .coverage/coverage.out | ||||
|  | ||||
| clean: | ||||
| 	@rm -f $(TEST_BINARIES) $(COVERAGE_BINARIES) codecov | ||||
| 	@rm -rf image $(COVERAGE_PATH) | ||||
|  | ||||
| rpc/rpc.proto: | ||||
| 	curl -sSL https://raw.githubusercontent.com/checkpoint-restore/criu/master/images/rpc.proto -o $@ | ||||
|  | ||||
| stats/stats.proto: | ||||
| 	curl -sSL https://raw.githubusercontent.com/checkpoint-restore/criu/master/images/stats.proto -o $@ | ||||
|  | ||||
| rpc/rpc.pb.go: rpc/rpc.proto | ||||
| 	protoc --go_out=. --go_opt=M$^=rpc/ $^ | ||||
|  | ||||
| stats/stats.pb.go: stats/stats.proto | ||||
| 	protoc --go_out=. --go_opt=M$^=stats/ $^ | ||||
|  | ||||
| vendor: | ||||
| 	GO111MODULE=on $(GO) mod tidy | ||||
| 	GO111MODULE=on $(GO) mod vendor | ||||
| 	GO111MODULE=on $(GO) mod verify | ||||
|  | ||||
| codecov: | ||||
| 	curl -Os https://uploader.codecov.io/latest/linux/codecov | ||||
| 	chmod +x codecov | ||||
| 	./codecov -f '.coverage/coverage.out' | ||||
|  | ||||
| .PHONY: build test phaul-test test-bin clean lint vendor coverage codecov | ||||
							
								
								
									
										96
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										96
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,96 +0,0 @@ | ||||
| [](https://github.com/checkpoint-restore/go-criu/actions?query=workflow%3Aci) | ||||
| [](https://github.com/checkpoint-restore/go-criu/actions?query=workflow%3Averify) | ||||
| [](https://pkg.go.dev/github.com/checkpoint-restore/go-criu) | ||||
|  | ||||
| ## go-criu -- Go bindings for CRIU | ||||
|  | ||||
| This repository provides Go bindings for [CRIU](https://criu.org/). The code is based on the Go-based PHaul | ||||
| implementation from the CRIU repository. For easier inclusion into other Go projects the | ||||
| CRIU Go bindings have been moved to this repository. | ||||
|  | ||||
| The Go bindings provide an easy way to use the CRIU RPC calls from Go without the need | ||||
| to set up all the infrastructure to make the actual RPC connection to CRIU. | ||||
|  | ||||
| The following example would print the version of CRIU: | ||||
| ```go | ||||
| import ( | ||||
| 	"log" | ||||
|  | ||||
| 	"github.com/checkpoint-restore/go-criu/v5" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	c := criu.MakeCriu() | ||||
| 	version, err := c.GetCriuVersion() | ||||
| 	if err != nil { | ||||
| 		log.Fatalln(err) | ||||
| 	} | ||||
| 	log.Println(version) | ||||
| } | ||||
| ``` | ||||
|  | ||||
| or to just check if at least a certain CRIU version is installed: | ||||
|  | ||||
| ```go | ||||
| 	c := criu.MakeCriu() | ||||
| 	result, err := c.IsCriuAtLeast(31100) | ||||
| ``` | ||||
|  | ||||
| ## Releases | ||||
|  | ||||
| The first go-criu release was 3.11 based on CRIU 3.11. The initial plan | ||||
| was to follow CRIU so that go-criu would carry the same version number as | ||||
| CRIU. | ||||
|  | ||||
| As go-criu is imported in other projects and as Go modules are expected | ||||
| to follow Semantic Versioning go-criu will also follow Semantic Versioning | ||||
| starting with the 4.0.0 release. | ||||
|  | ||||
| The following table shows the relation between go-criu and criu versions: | ||||
|  | ||||
| | Major version  | Latest release | CRIU version | | ||||
| | -------------- | -------------- | ------------ | | ||||
| | v5             | 5.2.0          | 3.16         | | ||||
| | v5             | 5.0.0          | 3.15         | | ||||
| | v4             | 4.1.0          | 3.14         | | ||||
|  | ||||
| ## How to contribute | ||||
|  | ||||
| While bug fixes can first be identified via an "issue", that is not required. | ||||
| It's ok to just open up a PR with the fix, but make sure you include the same | ||||
| information you would have included in an issue - like how to reproduce it. | ||||
|  | ||||
| PRs for new features should include some background on what use cases the | ||||
| new code is trying to address. When possible and when it makes sense, try to | ||||
| break-up larger PRs into smaller ones - it's easier to review smaller | ||||
| code changes. But only if those smaller ones make sense as stand-alone PRs. | ||||
|  | ||||
| Regardless of the type of PR, all PRs should include: | ||||
| * well documented code changes | ||||
| * additional testcases. Ideally, they should fail w/o your code change applied | ||||
| * documentation changes | ||||
|  | ||||
| Squash your commits into logical pieces of work that might want to be reviewed | ||||
| separate from the rest of the PRs. Ideally, each commit should implement a | ||||
| single idea, and the PR branch should pass the tests at every commit. GitHub | ||||
| makes it easy to review the cumulative effect of many commits; so, when in | ||||
| doubt, use smaller commits. | ||||
|  | ||||
| PRs that fix issues should include a reference like `Closes #XXXX` in the | ||||
| commit message so that github will automatically close the referenced issue | ||||
| when the PR is merged. | ||||
|  | ||||
| Contributors must assert that they are in compliance with the [Developer | ||||
| Certificate of Origin 1.1](http://developercertificate.org/). This is achieved | ||||
| by adding a "Signed-off-by" line containing the contributor's name and e-mail | ||||
| to every commit message. Your signature certifies that you wrote the patch or | ||||
| otherwise have the right to pass it on as an open-source patch. | ||||
|  | ||||
| ### License and copyright | ||||
|  | ||||
| Unless mentioned otherwise in a specific file's header, all code in | ||||
| this project is released under the Apache 2.0 license. | ||||
|  | ||||
| The author of a change remains the copyright holder of their code | ||||
| (no copyright assignment). The list of authors and contributors can be | ||||
| retrieved from the git commit history and in some cases, the file headers. | ||||
							
								
								
									
										45
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/features.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										45
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/features.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,45 +0,0 @@ | ||||
| package criu | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/checkpoint-restore/go-criu/v5/rpc" | ||||
| ) | ||||
|  | ||||
| // Feature checking in go-criu is based on the libcriu feature checking function. | ||||
|  | ||||
| // Feature checking allows the user to check if CRIU supports | ||||
| // certain features. There are CRIU features which do not depend | ||||
| // on the version of CRIU but on kernel features or architecture. | ||||
| // | ||||
| // One example is memory tracking. Memory tracking can be disabled | ||||
| // in the kernel or there are architectures which do not support | ||||
| // it (aarch64 for example). By using the feature check a libcriu | ||||
| // user can easily query CRIU if a certain feature is available. | ||||
| // | ||||
| // The features which should be checked can be marked in the | ||||
| // structure 'struct criu_feature_check'. Each structure member | ||||
| // that is set to true will result in CRIU checking for the | ||||
| // availability of that feature in the current combination of | ||||
| // CRIU/kernel/architecture. | ||||
| // | ||||
| // Available features will be set to true when the function | ||||
| // returns successfully. Missing features will be set to false. | ||||
|  | ||||
| func (c *Criu) FeatureCheck(features *rpc.CriuFeatures) (*rpc.CriuFeatures, error) { | ||||
| 	resp, err := c.doSwrkWithResp( | ||||
| 		rpc.CriuReqType_FEATURE_CHECK, | ||||
| 		nil, | ||||
| 		nil, | ||||
| 		features, | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if resp.GetType() != rpc.CriuReqType_FEATURE_CHECK { | ||||
| 		return nil, fmt.Errorf("Unexpected CRIU RPC response") | ||||
| 	} | ||||
|  | ||||
| 	return features, nil | ||||
| } | ||||
							
								
								
									
										264
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/main.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										264
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/main.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,264 +0,0 @@ | ||||
| package criu | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"strconv" | ||||
| 	"syscall" | ||||
|  | ||||
| 	"github.com/checkpoint-restore/go-criu/v5/rpc" | ||||
| 	"google.golang.org/protobuf/proto" | ||||
| ) | ||||
|  | ||||
| // Criu struct | ||||
| type Criu struct { | ||||
| 	swrkCmd  *exec.Cmd | ||||
| 	swrkSk   *os.File | ||||
| 	swrkPath string | ||||
| } | ||||
|  | ||||
| // MakeCriu returns the Criu object required for most operations | ||||
| func MakeCriu() *Criu { | ||||
| 	return &Criu{ | ||||
| 		swrkPath: "criu", | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // SetCriuPath allows setting the path to the CRIU binary | ||||
| // if it is in a non standard location | ||||
| func (c *Criu) SetCriuPath(path string) { | ||||
| 	c.swrkPath = path | ||||
| } | ||||
|  | ||||
| // Prepare sets up everything for the RPC communication to CRIU | ||||
| func (c *Criu) Prepare() error { | ||||
| 	fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_SEQPACKET, 0) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	cln := os.NewFile(uintptr(fds[0]), "criu-xprt-cln") | ||||
| 	syscall.CloseOnExec(fds[0]) | ||||
| 	srv := os.NewFile(uintptr(fds[1]), "criu-xprt-srv") | ||||
| 	defer srv.Close() | ||||
|  | ||||
| 	args := []string{"swrk", strconv.Itoa(fds[1])} | ||||
| 	// #nosec G204 | ||||
| 	cmd := exec.Command(c.swrkPath, args...) | ||||
|  | ||||
| 	err = cmd.Start() | ||||
| 	if err != nil { | ||||
| 		cln.Close() | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	c.swrkCmd = cmd | ||||
| 	c.swrkSk = cln | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Cleanup cleans up | ||||
| func (c *Criu) Cleanup() { | ||||
| 	if c.swrkCmd != nil { | ||||
| 		c.swrkSk.Close() | ||||
| 		c.swrkSk = nil | ||||
| 		_ = c.swrkCmd.Wait() | ||||
| 		c.swrkCmd = nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *Criu) sendAndRecv(reqB []byte) ([]byte, int, error) { | ||||
| 	cln := c.swrkSk | ||||
| 	_, err := cln.Write(reqB) | ||||
| 	if err != nil { | ||||
| 		return nil, 0, err | ||||
| 	} | ||||
|  | ||||
| 	respB := make([]byte, 2*4096) | ||||
| 	n, err := cln.Read(respB) | ||||
| 	if err != nil { | ||||
| 		return nil, 0, err | ||||
| 	} | ||||
|  | ||||
| 	return respB, n, nil | ||||
| } | ||||
|  | ||||
| func (c *Criu) doSwrk(reqType rpc.CriuReqType, opts *rpc.CriuOpts, nfy Notify) error { | ||||
| 	resp, err := c.doSwrkWithResp(reqType, opts, nfy, nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	respType := resp.GetType() | ||||
| 	if respType != reqType { | ||||
| 		return errors.New("unexpected CRIU RPC response") | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (c *Criu) doSwrkWithResp(reqType rpc.CriuReqType, opts *rpc.CriuOpts, nfy Notify, features *rpc.CriuFeatures) (*rpc.CriuResp, error) { | ||||
| 	var resp *rpc.CriuResp | ||||
|  | ||||
| 	req := rpc.CriuReq{ | ||||
| 		Type: &reqType, | ||||
| 		Opts: opts, | ||||
| 	} | ||||
|  | ||||
| 	if nfy != nil { | ||||
| 		opts.NotifyScripts = proto.Bool(true) | ||||
| 	} | ||||
|  | ||||
| 	if features != nil { | ||||
| 		req.Features = features | ||||
| 	} | ||||
|  | ||||
| 	if c.swrkCmd == nil { | ||||
| 		err := c.Prepare() | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		defer c.Cleanup() | ||||
| 	} | ||||
|  | ||||
| 	for { | ||||
| 		reqB, err := proto.Marshal(&req) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		respB, respS, err := c.sendAndRecv(reqB) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		resp = &rpc.CriuResp{} | ||||
| 		err = proto.Unmarshal(respB[:respS], resp) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		if !resp.GetSuccess() { | ||||
| 			return resp, fmt.Errorf("operation failed (msg:%s err:%d)", | ||||
| 				resp.GetCrErrmsg(), resp.GetCrErrno()) | ||||
| 		} | ||||
|  | ||||
| 		respType := resp.GetType() | ||||
| 		if respType != rpc.CriuReqType_NOTIFY { | ||||
| 			break | ||||
| 		} | ||||
| 		if nfy == nil { | ||||
| 			return resp, errors.New("unexpected notify") | ||||
| 		} | ||||
|  | ||||
| 		notify := resp.GetNotify() | ||||
| 		switch notify.GetScript() { | ||||
| 		case "pre-dump": | ||||
| 			err = nfy.PreDump() | ||||
| 		case "post-dump": | ||||
| 			err = nfy.PostDump() | ||||
| 		case "pre-restore": | ||||
| 			err = nfy.PreRestore() | ||||
| 		case "post-restore": | ||||
| 			err = nfy.PostRestore(notify.GetPid()) | ||||
| 		case "network-lock": | ||||
| 			err = nfy.NetworkLock() | ||||
| 		case "network-unlock": | ||||
| 			err = nfy.NetworkUnlock() | ||||
| 		case "setup-namespaces": | ||||
| 			err = nfy.SetupNamespaces(notify.GetPid()) | ||||
| 		case "post-setup-namespaces": | ||||
| 			err = nfy.PostSetupNamespaces() | ||||
| 		case "post-resume": | ||||
| 			err = nfy.PostResume() | ||||
| 		default: | ||||
| 			err = nil | ||||
| 		} | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return resp, err | ||||
| 		} | ||||
|  | ||||
| 		req = rpc.CriuReq{ | ||||
| 			Type:          &respType, | ||||
| 			NotifySuccess: proto.Bool(true), | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return resp, nil | ||||
| } | ||||
|  | ||||
| // Dump dumps a process | ||||
| func (c *Criu) Dump(opts *rpc.CriuOpts, nfy Notify) error { | ||||
| 	return c.doSwrk(rpc.CriuReqType_DUMP, opts, nfy) | ||||
| } | ||||
|  | ||||
| // Restore restores a process | ||||
| func (c *Criu) Restore(opts *rpc.CriuOpts, nfy Notify) error { | ||||
| 	return c.doSwrk(rpc.CriuReqType_RESTORE, opts, nfy) | ||||
| } | ||||
|  | ||||
| // PreDump does a pre-dump | ||||
| func (c *Criu) PreDump(opts *rpc.CriuOpts, nfy Notify) error { | ||||
| 	return c.doSwrk(rpc.CriuReqType_PRE_DUMP, opts, nfy) | ||||
| } | ||||
|  | ||||
| // StartPageServer starts the page server | ||||
| func (c *Criu) StartPageServer(opts *rpc.CriuOpts) error { | ||||
| 	return c.doSwrk(rpc.CriuReqType_PAGE_SERVER, opts, nil) | ||||
| } | ||||
|  | ||||
| // StartPageServerChld starts the page server and returns PID and port | ||||
| func (c *Criu) StartPageServerChld(opts *rpc.CriuOpts) (int, int, error) { | ||||
| 	resp, err := c.doSwrkWithResp(rpc.CriuReqType_PAGE_SERVER_CHLD, opts, nil, nil) | ||||
| 	if err != nil { | ||||
| 		return 0, 0, err | ||||
| 	} | ||||
|  | ||||
| 	return int(resp.Ps.GetPid()), int(resp.Ps.GetPort()), nil | ||||
| } | ||||
|  | ||||
| // GetCriuVersion executes the VERSION RPC call and returns the version | ||||
| // as an integer. Major * 10000 + Minor * 100 + SubLevel | ||||
| func (c *Criu) GetCriuVersion() (int, error) { | ||||
| 	resp, err := c.doSwrkWithResp(rpc.CriuReqType_VERSION, nil, nil, nil) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
|  | ||||
| 	if resp.GetType() != rpc.CriuReqType_VERSION { | ||||
| 		return 0, fmt.Errorf("Unexpected CRIU RPC response") | ||||
| 	} | ||||
|  | ||||
| 	version := int(*resp.GetVersion().MajorNumber) * 10000 | ||||
| 	version += int(*resp.GetVersion().MinorNumber) * 100 | ||||
| 	if resp.GetVersion().Sublevel != nil { | ||||
| 		version += int(*resp.GetVersion().Sublevel) | ||||
| 	} | ||||
|  | ||||
| 	if resp.GetVersion().Gitid != nil { | ||||
| 		// taken from runc: if it is a git release -> increase minor by 1 | ||||
| 		version -= (version % 100) | ||||
| 		version += 100 | ||||
| 	} | ||||
|  | ||||
| 	return version, nil | ||||
| } | ||||
|  | ||||
| // IsCriuAtLeast checks if the version is at least the same | ||||
| // as the parameter version | ||||
| func (c *Criu) IsCriuAtLeast(version int) (bool, error) { | ||||
| 	criuVersion, err := c.GetCriuVersion() | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
|  | ||||
| 	if criuVersion >= version { | ||||
| 		return true, nil | ||||
| 	} | ||||
|  | ||||
| 	return false, nil | ||||
| } | ||||
							
								
								
									
										62
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/notify.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										62
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/notify.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,62 +0,0 @@ | ||||
| package criu | ||||
|  | ||||
| // Notify interface | ||||
| type Notify interface { | ||||
| 	PreDump() error | ||||
| 	PostDump() error | ||||
| 	PreRestore() error | ||||
| 	PostRestore(pid int32) error | ||||
| 	NetworkLock() error | ||||
| 	NetworkUnlock() error | ||||
| 	SetupNamespaces(pid int32) error | ||||
| 	PostSetupNamespaces() error | ||||
| 	PostResume() error | ||||
| } | ||||
|  | ||||
| // NoNotify struct | ||||
| type NoNotify struct{} | ||||
|  | ||||
| // PreDump NoNotify | ||||
| func (c NoNotify) PreDump() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // PostDump NoNotify | ||||
| func (c NoNotify) PostDump() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // PreRestore NoNotify | ||||
| func (c NoNotify) PreRestore() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // PostRestore NoNotify | ||||
| func (c NoNotify) PostRestore(pid int32) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // NetworkLock NoNotify | ||||
| func (c NoNotify) NetworkLock() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // NetworkUnlock NoNotify | ||||
| func (c NoNotify) NetworkUnlock() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // SetupNamespaces NoNotify | ||||
| func (c NoNotify) SetupNamespaces(pid int32) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // PostSetupNamespaces NoNotify | ||||
| func (c NoNotify) PostSetupNamespaces() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // PostResume NoNotify | ||||
| func (c NoNotify) PostResume() error { | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										2237
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/rpc/rpc.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2237
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/rpc/rpc.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										239
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/rpc/rpc.proto
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										239
									
								
								vendor/github.com/checkpoint-restore/go-criu/v5/rpc/rpc.proto
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,239 +0,0 @@ | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| syntax = "proto2"; | ||||
|  | ||||
| message criu_page_server_info { | ||||
| 	optional string		address	= 1; | ||||
| 	optional int32		port	= 2; | ||||
| 	optional int32		pid	= 3; | ||||
| 	optional int32		fd	= 4; | ||||
| } | ||||
|  | ||||
| message criu_veth_pair { | ||||
| 	required string		if_in	= 1; | ||||
| 	required string		if_out	= 2; | ||||
| }; | ||||
|  | ||||
| message ext_mount_map { | ||||
| 	required string		key	= 1; | ||||
| 	required string		val	= 2; | ||||
| }; | ||||
|  | ||||
| message join_namespace { | ||||
| 	required string		ns		= 1; | ||||
| 	required string		ns_file		= 2; | ||||
| 	optional string		extra_opt	= 3; | ||||
| } | ||||
|  | ||||
| message inherit_fd { | ||||
| 	required string		key	= 1; | ||||
| 	required int32		fd	= 2; | ||||
| }; | ||||
|  | ||||
| message cgroup_root { | ||||
| 	optional string		ctrl	= 1; | ||||
| 	required string		path	= 2; | ||||
| }; | ||||
|  | ||||
| message unix_sk { | ||||
| 	required uint32		inode 	= 1; | ||||
| }; | ||||
|  | ||||
| enum criu_cg_mode { | ||||
| 	IGNORE	= 0; | ||||
| 	CG_NONE	= 1; | ||||
| 	PROPS	= 2; | ||||
| 	SOFT	= 3; | ||||
| 	FULL	= 4; | ||||
| 	STRICT	= 5; | ||||
| 	DEFAULT = 6; | ||||
| }; | ||||
|  | ||||
| enum criu_pre_dump_mode { | ||||
| 	SPLICE = 	1; | ||||
| 	VM_READ =	2; | ||||
| }; | ||||
|  | ||||
| message criu_opts { | ||||
| 	required int32			images_dir_fd	= 1; | ||||
| 	optional int32			pid		= 2; /* if not set on dump, will dump requesting process */ | ||||
|  | ||||
| 	optional bool			leave_running	= 3; | ||||
| 	optional bool			ext_unix_sk	= 4; | ||||
| 	optional bool			tcp_established	= 5; | ||||
| 	optional bool			evasive_devices	= 6; | ||||
| 	optional bool			shell_job	= 7; | ||||
| 	optional bool			file_locks	= 8; | ||||
| 	optional int32			log_level	= 9 [default = 2]; | ||||
| 	optional string			log_file	= 10; /* No subdirs are allowed. Consider using work-dir */ | ||||
|  | ||||
| 	optional criu_page_server_info	ps		= 11; | ||||
|  | ||||
| 	optional bool			notify_scripts	= 12; | ||||
|  | ||||
| 	optional string			root		= 13; | ||||
| 	optional string			parent_img	= 14; | ||||
| 	optional bool			track_mem	= 15; | ||||
| 	optional bool			auto_dedup	= 16; | ||||
|  | ||||
| 	optional int32			work_dir_fd	= 17; | ||||
| 	optional bool			link_remap	= 18; | ||||
| 	repeated criu_veth_pair		veths		= 19; /* DEPRECATED, use external instead */ | ||||
|  | ||||
| 	optional uint32			cpu_cap		= 20 [default = 0xffffffff]; | ||||
| 	optional bool			force_irmap	= 21; | ||||
| 	repeated string			exec_cmd	= 22; | ||||
|  | ||||
| 	repeated ext_mount_map		ext_mnt		= 23; /* DEPRECATED, use external instead */ | ||||
| 	optional bool			manage_cgroups	= 24; /* backward compatibility */ | ||||
| 	repeated cgroup_root		cg_root		= 25; | ||||
|  | ||||
| 	optional bool			rst_sibling	= 26; /* swrk only */ | ||||
| 	repeated inherit_fd		inherit_fd	= 27; /* swrk only */ | ||||
|  | ||||
| 	optional bool			auto_ext_mnt	= 28; | ||||
| 	optional bool			ext_sharing 	= 29; | ||||
| 	optional bool			ext_masters	= 30; | ||||
|  | ||||
| 	repeated string			skip_mnt	= 31; | ||||
| 	repeated string			enable_fs	= 32; | ||||
|  | ||||
| 	repeated unix_sk                unix_sk_ino     = 33; /* DEPRECATED, use external instead */ | ||||
|  | ||||
| 	optional criu_cg_mode		manage_cgroups_mode = 34; | ||||
| 	optional uint32			ghost_limit	= 35 [default = 0x100000]; | ||||
| 	repeated string			irmap_scan_paths = 36; | ||||
| 	repeated string			external	= 37; | ||||
| 	optional uint32			empty_ns	= 38; | ||||
| 	repeated join_namespace		join_ns		= 39; | ||||
|  | ||||
| 	optional string			cgroup_props		= 41; | ||||
| 	optional string			cgroup_props_file	= 42; | ||||
| 	repeated string			cgroup_dump_controller	= 43; | ||||
|  | ||||
| 	optional string			freeze_cgroup		= 44; | ||||
| 	optional uint32			timeout			= 45; | ||||
| 	optional bool			tcp_skip_in_flight	= 46; | ||||
| 	optional bool			weak_sysctls		= 47; | ||||
| 	optional bool			lazy_pages		= 48; | ||||
| 	optional int32			status_fd		= 49; | ||||
| 	optional bool			orphan_pts_master	= 50; | ||||
| 	optional string			config_file		= 51; | ||||
| 	optional bool			tcp_close		= 52; | ||||
| 	optional string			lsm_profile		= 53; | ||||
| 	optional string			tls_cacert		= 54; | ||||
| 	optional string			tls_cacrl		= 55; | ||||
| 	optional string			tls_cert		= 56; | ||||
| 	optional string			tls_key			= 57; | ||||
| 	optional bool			tls			= 58; | ||||
| 	optional bool			tls_no_cn_verify	= 59; | ||||
| 	optional string			cgroup_yard		= 60; | ||||
| 	optional criu_pre_dump_mode	pre_dump_mode		= 61 [default = SPLICE]; | ||||
| 	optional int32			pidfd_store_sk		= 62; | ||||
| 	optional string			lsm_mount_context	= 63; | ||||
| /*	optional bool			check_mounts		= 128;	*/ | ||||
| } | ||||
|  | ||||
| message criu_dump_resp { | ||||
| 	optional bool restored		= 1; | ||||
| } | ||||
|  | ||||
| message criu_restore_resp { | ||||
| 	required int32 pid		= 1; | ||||
| } | ||||
|  | ||||
| message criu_notify { | ||||
| 	optional string script		= 1; | ||||
| 	optional int32	pid		= 2; | ||||
| } | ||||
|  | ||||
| enum criu_req_type { | ||||
| 	EMPTY		= 0; | ||||
| 	DUMP		= 1; | ||||
| 	RESTORE		= 2; | ||||
| 	CHECK		= 3; | ||||
| 	PRE_DUMP	= 4; | ||||
| 	PAGE_SERVER	= 5; | ||||
|  | ||||
| 	NOTIFY		= 6; | ||||
|  | ||||
| 	CPUINFO_DUMP	= 7; | ||||
| 	CPUINFO_CHECK	= 8; | ||||
|  | ||||
| 	FEATURE_CHECK	= 9; | ||||
|  | ||||
| 	VERSION		= 10; | ||||
|  | ||||
| 	WAIT_PID	= 11; | ||||
| 	PAGE_SERVER_CHLD = 12; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * List of features which can queried via | ||||
|  * CRIU_REQ_TYPE__FEATURE_CHECK | ||||
|  */ | ||||
| message criu_features { | ||||
| 	optional bool			mem_track	= 1; | ||||
| 	optional bool			lazy_pages	= 2; | ||||
| 	optional bool			pidfd_store	= 3; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Request -- each type corresponds to must-be-there | ||||
|  * request arguments of respective type | ||||
|  */ | ||||
|  | ||||
| message criu_req { | ||||
| 	required criu_req_type		type		= 1; | ||||
|  | ||||
| 	optional criu_opts		opts		= 2; | ||||
| 	optional bool			notify_success	= 3; | ||||
|  | ||||
| 	/* | ||||
| 	 * When set service won't close the connection but | ||||
| 	 * will wait for more req-s to appear. Works not | ||||
| 	 * for all request types. | ||||
| 	 */ | ||||
| 	optional bool			keep_open	= 4; | ||||
| 	/* | ||||
| 	 * 'features' can be used to query which features | ||||
| 	 * are supported by the installed criu/kernel | ||||
| 	 * via RPC. | ||||
| 	 */ | ||||
| 	optional criu_features		features	= 5; | ||||
|  | ||||
| 	/* 'pid' is used for WAIT_PID */ | ||||
| 	optional uint32			pid		= 6; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Response -- it states whether the request was served | ||||
|  * and additional request-specific information | ||||
|  */ | ||||
|  | ||||
| message criu_resp { | ||||
| 	required criu_req_type		type		= 1; | ||||
| 	required bool			success		= 2; | ||||
|  | ||||
| 	optional criu_dump_resp		dump		= 3; | ||||
| 	optional criu_restore_resp	restore		= 4; | ||||
| 	optional criu_notify		notify		= 5; | ||||
| 	optional criu_page_server_info	ps		= 6; | ||||
|  | ||||
| 	optional int32			cr_errno	= 7; | ||||
| 	optional criu_features		features	= 8; | ||||
| 	optional string			cr_errmsg	= 9; | ||||
| 	optional criu_version		version		= 10; | ||||
|  | ||||
| 	optional int32			status		= 11; | ||||
| } | ||||
|  | ||||
| /* Answer for criu_req_type.VERSION requests */ | ||||
| message criu_version { | ||||
| 	required int32			major_number	= 1; | ||||
| 	required int32			minor_number	= 2; | ||||
| 	optional string			gitid		= 3; | ||||
| 	optional int32			sublevel	= 4; | ||||
| 	optional int32			extra		= 5; | ||||
| 	optional string			name		= 6; | ||||
| } | ||||
							
								
								
									
										20
									
								
								vendor/github.com/containerd/console/.golangci.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/containerd/console/.golangci.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,20 +0,0 @@ | ||||
| linters: | ||||
|   enable: | ||||
|     - gofmt | ||||
|     - goimports | ||||
|     - ineffassign | ||||
|     - misspell | ||||
|     - revive | ||||
|     - staticcheck | ||||
|     - structcheck | ||||
|     - unconvert | ||||
|     - unused | ||||
|     - varcheck | ||||
|     - vet | ||||
|   disable: | ||||
|     - errcheck | ||||
|  | ||||
| run: | ||||
|   timeout: 3m | ||||
|   skip-dirs: | ||||
|     - vendor | ||||
							
								
								
									
										191
									
								
								vendor/github.com/containerd/console/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/containerd/console/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,191 +0,0 @@ | ||||
|  | ||||
|                                  Apache License | ||||
|                            Version 2.0, January 2004 | ||||
|                         https://www.apache.org/licenses/ | ||||
|  | ||||
|    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
|  | ||||
|    1. Definitions. | ||||
|  | ||||
|       "License" shall mean the terms and conditions for use, reproduction, | ||||
|       and distribution as defined by Sections 1 through 9 of this document. | ||||
|  | ||||
|       "Licensor" shall mean the copyright owner or entity authorized by | ||||
|       the copyright owner that is granting the License. | ||||
|  | ||||
|       "Legal Entity" shall mean the union of the acting entity and all | ||||
|       other entities that control, are controlled by, or are under common | ||||
|       control with that entity. For the purposes of this definition, | ||||
|       "control" means (i) the power, direct or indirect, to cause the | ||||
|       direction or management of such entity, whether by contract or | ||||
|       otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
|       outstanding shares, or (iii) beneficial ownership of such entity. | ||||
|  | ||||
|       "You" (or "Your") shall mean an individual or Legal Entity | ||||
|       exercising permissions granted by this License. | ||||
|  | ||||
|       "Source" form shall mean the preferred form for making modifications, | ||||
|       including but not limited to software source code, documentation | ||||
|       source, and configuration files. | ||||
|  | ||||
|       "Object" form shall mean any form resulting from mechanical | ||||
|       transformation or translation of a Source form, including but | ||||
|       not limited to compiled object code, generated documentation, | ||||
|       and conversions to other media types. | ||||
|  | ||||
|       "Work" shall mean the work of authorship, whether in Source or | ||||
|       Object form, made available under the License, as indicated by a | ||||
|       copyright notice that is included in or attached to the work | ||||
|       (an example is provided in the Appendix below). | ||||
|  | ||||
|       "Derivative Works" shall mean any work, whether in Source or Object | ||||
|       form, that is based on (or derived from) the Work and for which the | ||||
|       editorial revisions, annotations, elaborations, or other modifications | ||||
|       represent, as a whole, an original work of authorship. For the purposes | ||||
|       of this License, Derivative Works shall not include works that remain | ||||
|       separable from, or merely link (or bind by name) to the interfaces of, | ||||
|       the Work and Derivative Works thereof. | ||||
|  | ||||
|       "Contribution" shall mean any work of authorship, including | ||||
|       the original version of the Work and any modifications or additions | ||||
|       to that Work or Derivative Works thereof, that is intentionally | ||||
|       submitted to Licensor for inclusion in the Work by the copyright owner | ||||
|       or by an individual or Legal Entity authorized to submit on behalf of | ||||
|       the copyright owner. For the purposes of this definition, "submitted" | ||||
|       means any form of electronic, verbal, or written communication sent | ||||
|       to the Licensor or its representatives, including but not limited to | ||||
|       communication on electronic mailing lists, source code control systems, | ||||
|       and issue tracking systems that are managed by, or on behalf of, the | ||||
|       Licensor for the purpose of discussing and improving the Work, but | ||||
|       excluding communication that is conspicuously marked or otherwise | ||||
|       designated in writing by the copyright owner as "Not a Contribution." | ||||
|  | ||||
|       "Contributor" shall mean Licensor and any individual or Legal Entity | ||||
|       on behalf of whom a Contribution has been received by Licensor and | ||||
|       subsequently incorporated within the Work. | ||||
|  | ||||
|    2. Grant of Copyright License. Subject to the terms and conditions of | ||||
|       this License, each Contributor hereby grants to You a perpetual, | ||||
|       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|       copyright license to reproduce, prepare Derivative Works of, | ||||
|       publicly display, publicly perform, sublicense, and distribute the | ||||
|       Work and such Derivative Works in Source or Object form. | ||||
|  | ||||
|    3. Grant of Patent License. Subject to the terms and conditions of | ||||
|       this License, each Contributor hereby grants to You a perpetual, | ||||
|       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|       (except as stated in this section) patent license to make, have made, | ||||
|       use, offer to sell, sell, import, and otherwise transfer the Work, | ||||
|       where such license applies only to those patent claims licensable | ||||
|       by such Contributor that are necessarily infringed by their | ||||
|       Contribution(s) alone or by combination of their Contribution(s) | ||||
|       with the Work to which such Contribution(s) was submitted. If You | ||||
|       institute patent litigation against any entity (including a | ||||
|       cross-claim or counterclaim in a lawsuit) alleging that the Work | ||||
|       or a Contribution incorporated within the Work constitutes direct | ||||
|       or contributory patent infringement, then any patent licenses | ||||
|       granted to You under this License for that Work shall terminate | ||||
|       as of the date such litigation is filed. | ||||
|  | ||||
|    4. Redistribution. You may reproduce and distribute copies of the | ||||
|       Work or Derivative Works thereof in any medium, with or without | ||||
|       modifications, and in Source or Object form, provided that You | ||||
|       meet the following conditions: | ||||
|  | ||||
|       (a) You must give any other recipients of the Work or | ||||
|           Derivative Works a copy of this License; and | ||||
|  | ||||
|       (b) You must cause any modified files to carry prominent notices | ||||
|           stating that You changed the files; and | ||||
|  | ||||
|       (c) You must retain, in the Source form of any Derivative Works | ||||
|           that You distribute, all copyright, patent, trademark, and | ||||
|           attribution notices from the Source form of the Work, | ||||
|           excluding those notices that do not pertain to any part of | ||||
|           the Derivative Works; and | ||||
|  | ||||
|       (d) If the Work includes a "NOTICE" text file as part of its | ||||
|           distribution, then any Derivative Works that You distribute must | ||||
|           include a readable copy of the attribution notices contained | ||||
|           within such NOTICE file, excluding those notices that do not | ||||
|           pertain to any part of the Derivative Works, in at least one | ||||
|           of the following places: within a NOTICE text file distributed | ||||
|           as part of the Derivative Works; within the Source form or | ||||
|           documentation, if provided along with the Derivative Works; or, | ||||
|           within a display generated by the Derivative Works, if and | ||||
|           wherever such third-party notices normally appear. The contents | ||||
|           of the NOTICE file are for informational purposes only and | ||||
|           do not modify the License. You may add Your own attribution | ||||
|           notices within Derivative Works that You distribute, alongside | ||||
|           or as an addendum to the NOTICE text from the Work, provided | ||||
|           that such additional attribution notices cannot be construed | ||||
|           as modifying the License. | ||||
|  | ||||
|       You may add Your own copyright statement to Your modifications and | ||||
|       may provide additional or different license terms and conditions | ||||
|       for use, reproduction, or distribution of Your modifications, or | ||||
|       for any such Derivative Works as a whole, provided Your use, | ||||
|       reproduction, and distribution of the Work otherwise complies with | ||||
|       the conditions stated in this License. | ||||
|  | ||||
|    5. Submission of Contributions. Unless You explicitly state otherwise, | ||||
|       any Contribution intentionally submitted for inclusion in the Work | ||||
|       by You to the Licensor shall be under the terms and conditions of | ||||
|       this License, without any additional terms or conditions. | ||||
|       Notwithstanding the above, nothing herein shall supersede or modify | ||||
|       the terms of any separate license agreement you may have executed | ||||
|       with Licensor regarding such Contributions. | ||||
|  | ||||
|    6. Trademarks. This License does not grant permission to use the trade | ||||
|       names, trademarks, service marks, or product names of the Licensor, | ||||
|       except as required for reasonable and customary use in describing the | ||||
|       origin of the Work and reproducing the content of the NOTICE file. | ||||
|  | ||||
|    7. Disclaimer of Warranty. Unless required by applicable law or | ||||
|       agreed to in writing, Licensor provides the Work (and each | ||||
|       Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
|       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||||
|       implied, including, without limitation, any warranties or conditions | ||||
|       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||||
|       PARTICULAR PURPOSE. You are solely responsible for determining the | ||||
|       appropriateness of using or redistributing the Work and assume any | ||||
|       risks associated with Your exercise of permissions under this License. | ||||
|  | ||||
|    8. Limitation of Liability. In no event and under no legal theory, | ||||
|       whether in tort (including negligence), contract, or otherwise, | ||||
|       unless required by applicable law (such as deliberate and grossly | ||||
|       negligent acts) or agreed to in writing, shall any Contributor be | ||||
|       liable to You for damages, including any direct, indirect, special, | ||||
|       incidental, or consequential damages of any character arising as a | ||||
|       result of this License or out of the use or inability to use the | ||||
|       Work (including but not limited to damages for loss of goodwill, | ||||
|       work stoppage, computer failure or malfunction, or any and all | ||||
|       other commercial damages or losses), even if such Contributor | ||||
|       has been advised of the possibility of such damages. | ||||
|  | ||||
|    9. Accepting Warranty or Additional Liability. While redistributing | ||||
|       the Work or Derivative Works thereof, You may choose to offer, | ||||
|       and charge a fee for, acceptance of support, warranty, indemnity, | ||||
|       or other liability obligations and/or rights consistent with this | ||||
|       License. However, in accepting such obligations, You may act only | ||||
|       on Your own behalf and on Your sole responsibility, not on behalf | ||||
|       of any other Contributor, and only if You agree to indemnify, | ||||
|       defend, and hold each Contributor harmless for any liability | ||||
|       incurred by, or claims asserted against, such Contributor by reason | ||||
|       of your accepting any such warranty or additional liability. | ||||
|  | ||||
|    END OF TERMS AND CONDITIONS | ||||
|  | ||||
|    Copyright The containerd Authors | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        https://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
							
								
								
									
										29
									
								
								vendor/github.com/containerd/console/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/containerd/console/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,29 +0,0 @@ | ||||
| # console | ||||
|  | ||||
| [](https://pkg.go.dev/github.com/containerd/console) | ||||
| [](https://github.com/containerd/console/actions?query=workflow%3ACI) | ||||
| [](https://goreportcard.com/report/github.com/containerd/console) | ||||
|  | ||||
| Golang package for dealing with consoles.  Light on deps and a simple API. | ||||
|  | ||||
| ## Modifying the current process | ||||
|  | ||||
| ```go | ||||
| current := console.Current() | ||||
| defer current.Reset() | ||||
|  | ||||
| if err := current.SetRaw(); err != nil { | ||||
| } | ||||
| ws, err := current.Size() | ||||
| current.Resize(ws) | ||||
| ``` | ||||
|  | ||||
| ## Project details | ||||
|  | ||||
| console is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE). | ||||
| As a containerd sub-project, you will find the: | ||||
|  * [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md), | ||||
|  * [Maintainers](https://github.com/containerd/project/blob/main/MAINTAINERS), | ||||
|  * and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md) | ||||
|  | ||||
| information in our [`containerd/project`](https://github.com/containerd/project) repository. | ||||
							
								
								
									
										90
									
								
								vendor/github.com/containerd/console/console.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										90
									
								
								vendor/github.com/containerd/console/console.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,90 +0,0 @@ | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	ErrNotAConsole    = errors.New("provided file is not a console") | ||||
| 	ErrNotImplemented = errors.New("not implemented") | ||||
| ) | ||||
|  | ||||
| type File interface { | ||||
| 	io.ReadWriteCloser | ||||
|  | ||||
| 	// Fd returns its file descriptor | ||||
| 	Fd() uintptr | ||||
| 	// Name returns its file name | ||||
| 	Name() string | ||||
| } | ||||
|  | ||||
| type Console interface { | ||||
| 	File | ||||
|  | ||||
| 	// Resize resizes the console to the provided window size | ||||
| 	Resize(WinSize) error | ||||
| 	// ResizeFrom resizes the calling console to the size of the | ||||
| 	// provided console | ||||
| 	ResizeFrom(Console) error | ||||
| 	// SetRaw sets the console in raw mode | ||||
| 	SetRaw() error | ||||
| 	// DisableEcho disables echo on the console | ||||
| 	DisableEcho() error | ||||
| 	// Reset restores the console to its original state | ||||
| 	Reset() error | ||||
| 	// Size returns the window size of the console | ||||
| 	Size() (WinSize, error) | ||||
| } | ||||
|  | ||||
| // WinSize specifies the window size of the console | ||||
| type WinSize struct { | ||||
| 	// Height of the console | ||||
| 	Height uint16 | ||||
| 	// Width of the console | ||||
| 	Width uint16 | ||||
| 	x     uint16 | ||||
| 	y     uint16 | ||||
| } | ||||
|  | ||||
| // Current returns the current process' console | ||||
| func Current() (c Console) { | ||||
| 	var err error | ||||
| 	// Usually all three streams (stdin, stdout, and stderr) | ||||
| 	// are open to the same console, but some might be redirected, | ||||
| 	// so try all three. | ||||
| 	for _, s := range []*os.File{os.Stderr, os.Stdout, os.Stdin} { | ||||
| 		if c, err = ConsoleFromFile(s); err == nil { | ||||
| 			return c | ||||
| 		} | ||||
| 	} | ||||
| 	// One of the std streams should always be a console | ||||
| 	// for the design of this function. | ||||
| 	panic(err) | ||||
| } | ||||
|  | ||||
| // ConsoleFromFile returns a console using the provided file | ||||
| // nolint:revive | ||||
| func ConsoleFromFile(f File) (Console, error) { | ||||
| 	if err := checkConsole(f); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return newMaster(f) | ||||
| } | ||||
							
								
								
									
										281
									
								
								vendor/github.com/containerd/console/console_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										281
									
								
								vendor/github.com/containerd/console/console_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,281 +0,0 @@ | ||||
| //go:build linux | ||||
| // +build linux | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"sync" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	maxEvents = 128 | ||||
| ) | ||||
|  | ||||
| // Epoller manages multiple epoll consoles using edge-triggered epoll api so we | ||||
| // dont have to deal with repeated wake-up of EPOLLER or EPOLLHUP. | ||||
| // For more details, see: | ||||
| // - https://github.com/systemd/systemd/pull/4262 | ||||
| // - https://github.com/moby/moby/issues/27202 | ||||
| // | ||||
| // Example usage of Epoller and EpollConsole can be as follow: | ||||
| // | ||||
| //	epoller, _ := NewEpoller() | ||||
| //	epollConsole, _ := epoller.Add(console) | ||||
| //	go epoller.Wait() | ||||
| //	var ( | ||||
| //		b  bytes.Buffer | ||||
| //		wg sync.WaitGroup | ||||
| //	) | ||||
| //	wg.Add(1) | ||||
| //	go func() { | ||||
| //		io.Copy(&b, epollConsole) | ||||
| //		wg.Done() | ||||
| //	}() | ||||
| //	// perform I/O on the console | ||||
| //	epollConsole.Shutdown(epoller.CloseConsole) | ||||
| //	wg.Wait() | ||||
| //	epollConsole.Close() | ||||
| type Epoller struct { | ||||
| 	efd       int | ||||
| 	mu        sync.Mutex | ||||
| 	fdMapping map[int]*EpollConsole | ||||
| 	closeOnce sync.Once | ||||
| } | ||||
|  | ||||
| // NewEpoller returns an instance of epoller with a valid epoll fd. | ||||
| func NewEpoller() (*Epoller, error) { | ||||
| 	efd, err := unix.EpollCreate1(unix.EPOLL_CLOEXEC) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &Epoller{ | ||||
| 		efd:       efd, | ||||
| 		fdMapping: make(map[int]*EpollConsole), | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // Add creates an epoll console based on the provided console. The console will | ||||
| // be registered with EPOLLET (i.e. using edge-triggered notification) and its | ||||
| // file descriptor will be set to non-blocking mode. After this, user should use | ||||
| // the return console to perform I/O. | ||||
| func (e *Epoller) Add(console Console) (*EpollConsole, error) { | ||||
| 	sysfd := int(console.Fd()) | ||||
| 	// Set sysfd to non-blocking mode | ||||
| 	if err := unix.SetNonblock(sysfd, true); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	ev := unix.EpollEvent{ | ||||
| 		Events: unix.EPOLLIN | unix.EPOLLOUT | unix.EPOLLRDHUP | unix.EPOLLET, | ||||
| 		Fd:     int32(sysfd), | ||||
| 	} | ||||
| 	if err := unix.EpollCtl(e.efd, unix.EPOLL_CTL_ADD, sysfd, &ev); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	ef := &EpollConsole{ | ||||
| 		Console: console, | ||||
| 		sysfd:   sysfd, | ||||
| 		readc:   sync.NewCond(&sync.Mutex{}), | ||||
| 		writec:  sync.NewCond(&sync.Mutex{}), | ||||
| 	} | ||||
| 	e.mu.Lock() | ||||
| 	e.fdMapping[sysfd] = ef | ||||
| 	e.mu.Unlock() | ||||
| 	return ef, nil | ||||
| } | ||||
|  | ||||
| // Wait starts the loop to wait for its consoles' notifications and signal | ||||
| // appropriate console that it can perform I/O. | ||||
| func (e *Epoller) Wait() error { | ||||
| 	events := make([]unix.EpollEvent, maxEvents) | ||||
| 	for { | ||||
| 		n, err := unix.EpollWait(e.efd, events, -1) | ||||
| 		if err != nil { | ||||
| 			// EINTR: The call was interrupted by a signal handler before either | ||||
| 			// any of the requested events occurred or the timeout expired | ||||
| 			if err == unix.EINTR { | ||||
| 				continue | ||||
| 			} | ||||
| 			return err | ||||
| 		} | ||||
| 		for i := 0; i < n; i++ { | ||||
| 			ev := &events[i] | ||||
| 			// the console is ready to be read from | ||||
| 			if ev.Events&(unix.EPOLLIN|unix.EPOLLHUP|unix.EPOLLERR) != 0 { | ||||
| 				if epfile := e.getConsole(int(ev.Fd)); epfile != nil { | ||||
| 					epfile.signalRead() | ||||
| 				} | ||||
| 			} | ||||
| 			// the console is ready to be written to | ||||
| 			if ev.Events&(unix.EPOLLOUT|unix.EPOLLHUP|unix.EPOLLERR) != 0 { | ||||
| 				if epfile := e.getConsole(int(ev.Fd)); epfile != nil { | ||||
| 					epfile.signalWrite() | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // CloseConsole unregisters the console's file descriptor from epoll interface | ||||
| func (e *Epoller) CloseConsole(fd int) error { | ||||
| 	e.mu.Lock() | ||||
| 	defer e.mu.Unlock() | ||||
| 	delete(e.fdMapping, fd) | ||||
| 	return unix.EpollCtl(e.efd, unix.EPOLL_CTL_DEL, fd, &unix.EpollEvent{}) | ||||
| } | ||||
|  | ||||
| func (e *Epoller) getConsole(sysfd int) *EpollConsole { | ||||
| 	e.mu.Lock() | ||||
| 	f := e.fdMapping[sysfd] | ||||
| 	e.mu.Unlock() | ||||
| 	return f | ||||
| } | ||||
|  | ||||
| // Close closes the epoll fd | ||||
| func (e *Epoller) Close() error { | ||||
| 	closeErr := os.ErrClosed // default to "file already closed" | ||||
| 	e.closeOnce.Do(func() { | ||||
| 		closeErr = unix.Close(e.efd) | ||||
| 	}) | ||||
| 	return closeErr | ||||
| } | ||||
|  | ||||
| // EpollConsole acts like a console but registers its file descriptor with an | ||||
| // epoll fd and uses epoll API to perform I/O. | ||||
| type EpollConsole struct { | ||||
| 	Console | ||||
| 	readc  *sync.Cond | ||||
| 	writec *sync.Cond | ||||
| 	sysfd  int | ||||
| 	closed bool | ||||
| } | ||||
|  | ||||
| // Read reads up to len(p) bytes into p. It returns the number of bytes read | ||||
| // (0 <= n <= len(p)) and any error encountered. | ||||
| // | ||||
| // If the console's read returns EAGAIN or EIO, we assume that it's a | ||||
| // temporary error because the other side went away and wait for the signal | ||||
| // generated by epoll event to continue. | ||||
| func (ec *EpollConsole) Read(p []byte) (n int, err error) { | ||||
| 	var read int | ||||
| 	ec.readc.L.Lock() | ||||
| 	defer ec.readc.L.Unlock() | ||||
| 	for { | ||||
| 		read, err = ec.Console.Read(p[n:]) | ||||
| 		n += read | ||||
| 		if err != nil { | ||||
| 			var hangup bool | ||||
| 			if perr, ok := err.(*os.PathError); ok { | ||||
| 				hangup = (perr.Err == unix.EAGAIN || perr.Err == unix.EIO) | ||||
| 			} else { | ||||
| 				hangup = (err == unix.EAGAIN || err == unix.EIO) | ||||
| 			} | ||||
| 			// if the other end disappear, assume this is temporary and wait for the | ||||
| 			// signal to continue again. Unless we didnt read anything and the | ||||
| 			// console is already marked as closed then we should exit | ||||
| 			if hangup && !(n == 0 && len(p) > 0 && ec.closed) { | ||||
| 				ec.readc.Wait() | ||||
| 				continue | ||||
| 			} | ||||
| 		} | ||||
| 		break | ||||
| 	} | ||||
| 	// if we didnt read anything then return io.EOF to end gracefully | ||||
| 	if n == 0 && len(p) > 0 && err == nil { | ||||
| 		err = io.EOF | ||||
| 	} | ||||
| 	// signal for others that we finished the read | ||||
| 	ec.readc.Signal() | ||||
| 	return n, err | ||||
| } | ||||
|  | ||||
| // Writes len(p) bytes from p to the console. It returns the number of bytes | ||||
| // written from p (0 <= n <= len(p)) and any error encountered that caused | ||||
| // the write to stop early. | ||||
| // | ||||
| // If writes to the console returns EAGAIN or EIO, we assume that it's a | ||||
| // temporary error because the other side went away and wait for the signal | ||||
| // generated by epoll event to continue. | ||||
| func (ec *EpollConsole) Write(p []byte) (n int, err error) { | ||||
| 	var written int | ||||
| 	ec.writec.L.Lock() | ||||
| 	defer ec.writec.L.Unlock() | ||||
| 	for { | ||||
| 		written, err = ec.Console.Write(p[n:]) | ||||
| 		n += written | ||||
| 		if err != nil { | ||||
| 			var hangup bool | ||||
| 			if perr, ok := err.(*os.PathError); ok { | ||||
| 				hangup = (perr.Err == unix.EAGAIN || perr.Err == unix.EIO) | ||||
| 			} else { | ||||
| 				hangup = (err == unix.EAGAIN || err == unix.EIO) | ||||
| 			} | ||||
| 			// if the other end disappears, assume this is temporary and wait for the | ||||
| 			// signal to continue again. | ||||
| 			if hangup { | ||||
| 				ec.writec.Wait() | ||||
| 				continue | ||||
| 			} | ||||
| 		} | ||||
| 		// unrecoverable error, break the loop and return the error | ||||
| 		break | ||||
| 	} | ||||
| 	if n < len(p) && err == nil { | ||||
| 		err = io.ErrShortWrite | ||||
| 	} | ||||
| 	// signal for others that we finished the write | ||||
| 	ec.writec.Signal() | ||||
| 	return n, err | ||||
| } | ||||
|  | ||||
| // Shutdown closes the file descriptor and signals call waiters for this fd. | ||||
| // It accepts a callback which will be called with the console's fd. The | ||||
| // callback typically will be used to do further cleanup such as unregister the | ||||
| // console's fd from the epoll interface. | ||||
| // User should call Shutdown and wait for all I/O operation to be finished | ||||
| // before closing the console. | ||||
| func (ec *EpollConsole) Shutdown(close func(int) error) error { | ||||
| 	ec.readc.L.Lock() | ||||
| 	defer ec.readc.L.Unlock() | ||||
| 	ec.writec.L.Lock() | ||||
| 	defer ec.writec.L.Unlock() | ||||
|  | ||||
| 	ec.readc.Broadcast() | ||||
| 	ec.writec.Broadcast() | ||||
| 	ec.closed = true | ||||
| 	return close(ec.sysfd) | ||||
| } | ||||
|  | ||||
| // signalRead signals that the console is readable. | ||||
| func (ec *EpollConsole) signalRead() { | ||||
| 	ec.readc.L.Lock() | ||||
| 	ec.readc.Signal() | ||||
| 	ec.readc.L.Unlock() | ||||
| } | ||||
|  | ||||
| // signalWrite signals that the console is writable. | ||||
| func (ec *EpollConsole) signalWrite() { | ||||
| 	ec.writec.L.Lock() | ||||
| 	ec.writec.Signal() | ||||
| 	ec.writec.L.Unlock() | ||||
| } | ||||
							
								
								
									
										36
									
								
								vendor/github.com/containerd/console/console_other.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										36
									
								
								vendor/github.com/containerd/console/console_other.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,36 +0,0 @@ | ||||
| //go:build !darwin && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows && !zos | ||||
| // +build !darwin,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| // NewPty creates a new pty pair | ||||
| // The master is returned as the first console and a string | ||||
| // with the path to the pty slave is returned as the second | ||||
| func NewPty() (Console, string, error) { | ||||
| 	return nil, "", ErrNotImplemented | ||||
| } | ||||
|  | ||||
| // checkConsole checks if the provided file is a console | ||||
| func checkConsole(f File) error { | ||||
| 	return ErrNotAConsole | ||||
| } | ||||
|  | ||||
| func newMaster(f File) (Console, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
							
								
								
									
										157
									
								
								vendor/github.com/containerd/console/console_unix.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										157
									
								
								vendor/github.com/containerd/console/console_unix.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,157 +0,0 @@ | ||||
| //go:build darwin || freebsd || linux || netbsd || openbsd || zos | ||||
| // +build darwin freebsd linux netbsd openbsd zos | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| // NewPty creates a new pty pair | ||||
| // The master is returned as the first console and a string | ||||
| // with the path to the pty slave is returned as the second | ||||
| func NewPty() (Console, string, error) { | ||||
| 	f, err := openpt() | ||||
| 	if err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	slave, err := ptsname(f) | ||||
| 	if err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	if err := unlockpt(f); err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	m, err := newMaster(f) | ||||
| 	if err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	return m, slave, nil | ||||
| } | ||||
|  | ||||
| type master struct { | ||||
| 	f        File | ||||
| 	original *unix.Termios | ||||
| } | ||||
|  | ||||
| func (m *master) Read(b []byte) (int, error) { | ||||
| 	return m.f.Read(b) | ||||
| } | ||||
|  | ||||
| func (m *master) Write(b []byte) (int, error) { | ||||
| 	return m.f.Write(b) | ||||
| } | ||||
|  | ||||
| func (m *master) Close() error { | ||||
| 	return m.f.Close() | ||||
| } | ||||
|  | ||||
| func (m *master) Resize(ws WinSize) error { | ||||
| 	return tcswinsz(m.f.Fd(), ws) | ||||
| } | ||||
|  | ||||
| func (m *master) ResizeFrom(c Console) error { | ||||
| 	ws, err := c.Size() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return m.Resize(ws) | ||||
| } | ||||
|  | ||||
| func (m *master) Reset() error { | ||||
| 	if m.original == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return tcset(m.f.Fd(), m.original) | ||||
| } | ||||
|  | ||||
| func (m *master) getCurrent() (unix.Termios, error) { | ||||
| 	var termios unix.Termios | ||||
| 	if err := tcget(m.f.Fd(), &termios); err != nil { | ||||
| 		return unix.Termios{}, err | ||||
| 	} | ||||
| 	return termios, nil | ||||
| } | ||||
|  | ||||
| func (m *master) SetRaw() error { | ||||
| 	rawState, err := m.getCurrent() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	rawState = cfmakeraw(rawState) | ||||
| 	rawState.Oflag = rawState.Oflag | unix.OPOST | ||||
| 	return tcset(m.f.Fd(), &rawState) | ||||
| } | ||||
|  | ||||
| func (m *master) DisableEcho() error { | ||||
| 	rawState, err := m.getCurrent() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	rawState.Lflag = rawState.Lflag &^ unix.ECHO | ||||
| 	return tcset(m.f.Fd(), &rawState) | ||||
| } | ||||
|  | ||||
| func (m *master) Size() (WinSize, error) { | ||||
| 	return tcgwinsz(m.f.Fd()) | ||||
| } | ||||
|  | ||||
| func (m *master) Fd() uintptr { | ||||
| 	return m.f.Fd() | ||||
| } | ||||
|  | ||||
| func (m *master) Name() string { | ||||
| 	return m.f.Name() | ||||
| } | ||||
|  | ||||
| // checkConsole checks if the provided file is a console | ||||
| func checkConsole(f File) error { | ||||
| 	var termios unix.Termios | ||||
| 	if tcget(f.Fd(), &termios) != nil { | ||||
| 		return ErrNotAConsole | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func newMaster(f File) (Console, error) { | ||||
| 	m := &master{ | ||||
| 		f: f, | ||||
| 	} | ||||
| 	t, err := m.getCurrent() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	m.original = &t | ||||
| 	return m, nil | ||||
| } | ||||
|  | ||||
| // ClearONLCR sets the necessary tty_ioctl(4)s to ensure that a pty pair | ||||
| // created by us acts normally. In particular, a not-very-well-known default of | ||||
| // Linux unix98 ptys is that they have +onlcr by default. While this isn't a | ||||
| // problem for terminal emulators, because we relay data from the terminal we | ||||
| // also relay that funky line discipline. | ||||
| func ClearONLCR(fd uintptr) error { | ||||
| 	return setONLCR(fd, false) | ||||
| } | ||||
|  | ||||
| // SetONLCR sets the necessary tty_ioctl(4)s to ensure that a pty pair | ||||
| // created by us acts as intended for a terminal emulator. | ||||
| func SetONLCR(fd uintptr) error { | ||||
| 	return setONLCR(fd, true) | ||||
| } | ||||
							
								
								
									
										219
									
								
								vendor/github.com/containerd/console/console_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										219
									
								
								vendor/github.com/containerd/console/console_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,219 +0,0 @@ | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
|  | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
|  | ||||
| var vtInputSupported bool | ||||
|  | ||||
| func (m *master) initStdios() { | ||||
| 	// Note: We discard console mode warnings, because in/out can be redirected. | ||||
| 	// | ||||
| 	// TODO: Investigate opening CONOUT$/CONIN$ to handle this correctly | ||||
|  | ||||
| 	m.in = windows.Handle(os.Stdin.Fd()) | ||||
| 	if err := windows.GetConsoleMode(m.in, &m.inMode); err == nil { | ||||
| 		// Validate that windows.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it. | ||||
| 		if err = windows.SetConsoleMode(m.in, m.inMode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err == nil { | ||||
| 			vtInputSupported = true | ||||
| 		} | ||||
| 		// Unconditionally set the console mode back even on failure because SetConsoleMode | ||||
| 		// remembers invalid bits on input handles. | ||||
| 		windows.SetConsoleMode(m.in, m.inMode) | ||||
| 	} | ||||
|  | ||||
| 	m.out = windows.Handle(os.Stdout.Fd()) | ||||
| 	if err := windows.GetConsoleMode(m.out, &m.outMode); err == nil { | ||||
| 		if err := windows.SetConsoleMode(m.out, m.outMode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err == nil { | ||||
| 			m.outMode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING | ||||
| 		} else { | ||||
| 			windows.SetConsoleMode(m.out, m.outMode) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	m.err = windows.Handle(os.Stderr.Fd()) | ||||
| 	if err := windows.GetConsoleMode(m.err, &m.errMode); err == nil { | ||||
| 		if err := windows.SetConsoleMode(m.err, m.errMode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err == nil { | ||||
| 			m.errMode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING | ||||
| 		} else { | ||||
| 			windows.SetConsoleMode(m.err, m.errMode) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type master struct { | ||||
| 	in     windows.Handle | ||||
| 	inMode uint32 | ||||
|  | ||||
| 	out     windows.Handle | ||||
| 	outMode uint32 | ||||
|  | ||||
| 	err     windows.Handle | ||||
| 	errMode uint32 | ||||
| } | ||||
|  | ||||
| func (m *master) SetRaw() error { | ||||
| 	if err := makeInputRaw(m.in, m.inMode); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Set StdOut and StdErr to raw mode, we ignore failures since | ||||
| 	// windows.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this version of | ||||
| 	// Windows. | ||||
|  | ||||
| 	windows.SetConsoleMode(m.out, m.outMode|windows.DISABLE_NEWLINE_AUTO_RETURN) | ||||
|  | ||||
| 	windows.SetConsoleMode(m.err, m.errMode|windows.DISABLE_NEWLINE_AUTO_RETURN) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *master) Reset() error { | ||||
| 	var errs []error | ||||
|  | ||||
| 	for _, s := range []struct { | ||||
| 		fd   windows.Handle | ||||
| 		mode uint32 | ||||
| 	}{ | ||||
| 		{m.in, m.inMode}, | ||||
| 		{m.out, m.outMode}, | ||||
| 		{m.err, m.errMode}, | ||||
| 	} { | ||||
| 		if err := windows.SetConsoleMode(s.fd, s.mode); err != nil { | ||||
| 			// we can't just abort on the first error, otherwise we might leave | ||||
| 			// the console in an unexpected state. | ||||
| 			errs = append(errs, fmt.Errorf("unable to restore console mode: %w", err)) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(errs) > 0 { | ||||
| 		return errs[0] | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *master) Size() (WinSize, error) { | ||||
| 	var info windows.ConsoleScreenBufferInfo | ||||
| 	err := windows.GetConsoleScreenBufferInfo(m.out, &info) | ||||
| 	if err != nil { | ||||
| 		return WinSize{}, fmt.Errorf("unable to get console info: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	winsize := WinSize{ | ||||
| 		Width:  uint16(info.Window.Right - info.Window.Left + 1), | ||||
| 		Height: uint16(info.Window.Bottom - info.Window.Top + 1), | ||||
| 	} | ||||
|  | ||||
| 	return winsize, nil | ||||
| } | ||||
|  | ||||
| func (m *master) Resize(ws WinSize) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (m *master) ResizeFrom(c Console) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (m *master) DisableEcho() error { | ||||
| 	mode := m.inMode &^ windows.ENABLE_ECHO_INPUT | ||||
| 	mode |= windows.ENABLE_PROCESSED_INPUT | ||||
| 	mode |= windows.ENABLE_LINE_INPUT | ||||
|  | ||||
| 	if err := windows.SetConsoleMode(m.in, mode); err != nil { | ||||
| 		return fmt.Errorf("unable to set console to disable echo: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *master) Close() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *master) Read(b []byte) (int, error) { | ||||
| 	return os.Stdin.Read(b) | ||||
| } | ||||
|  | ||||
| func (m *master) Write(b []byte) (int, error) { | ||||
| 	return os.Stdout.Write(b) | ||||
| } | ||||
|  | ||||
| func (m *master) Fd() uintptr { | ||||
| 	return uintptr(m.in) | ||||
| } | ||||
|  | ||||
| // on windows, console can only be made from os.Std{in,out,err}, hence there | ||||
| // isnt a single name here we can use. Return a dummy "console" value in this | ||||
| // case should be sufficient. | ||||
| func (m *master) Name() string { | ||||
| 	return "console" | ||||
| } | ||||
|  | ||||
| // makeInputRaw puts the terminal (Windows Console) connected to the given | ||||
| // file descriptor into raw mode | ||||
| func makeInputRaw(fd windows.Handle, mode uint32) error { | ||||
| 	// See | ||||
| 	// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx | ||||
| 	// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx | ||||
|  | ||||
| 	// Disable these modes | ||||
| 	mode &^= windows.ENABLE_ECHO_INPUT | ||||
| 	mode &^= windows.ENABLE_LINE_INPUT | ||||
| 	mode &^= windows.ENABLE_MOUSE_INPUT | ||||
| 	mode &^= windows.ENABLE_WINDOW_INPUT | ||||
| 	mode &^= windows.ENABLE_PROCESSED_INPUT | ||||
|  | ||||
| 	// Enable these modes | ||||
| 	mode |= windows.ENABLE_EXTENDED_FLAGS | ||||
| 	mode |= windows.ENABLE_INSERT_MODE | ||||
| 	mode |= windows.ENABLE_QUICK_EDIT_MODE | ||||
|  | ||||
| 	if vtInputSupported { | ||||
| 		mode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT | ||||
| 	} | ||||
|  | ||||
| 	if err := windows.SetConsoleMode(fd, mode); err != nil { | ||||
| 		return fmt.Errorf("unable to set console to raw mode: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func checkConsole(f File) error { | ||||
| 	var mode uint32 | ||||
| 	if err := windows.GetConsoleMode(windows.Handle(f.Fd()), &mode); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func newMaster(f File) (Console, error) { | ||||
| 	if f != os.Stdin && f != os.Stdout && f != os.Stderr { | ||||
| 		return nil, errors.New("creating a console from a file is not supported on windows") | ||||
| 	} | ||||
| 	m := &master{} | ||||
| 	m.initStdios() | ||||
| 	return m, nil | ||||
| } | ||||
							
								
								
									
										46
									
								
								vendor/github.com/containerd/console/pty_freebsd_cgo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										46
									
								
								vendor/github.com/containerd/console/pty_freebsd_cgo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,46 +0,0 @@ | ||||
| //go:build freebsd && cgo | ||||
| // +build freebsd,cgo | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| /* | ||||
| #include <fcntl.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| */ | ||||
| import "C" | ||||
|  | ||||
| // openpt allocates a new pseudo-terminal and establishes a connection with its | ||||
| // control device. | ||||
| func openpt() (*os.File, error) { | ||||
| 	fd, err := C.posix_openpt(C.O_RDWR) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("posix_openpt: %w", err) | ||||
| 	} | ||||
| 	if _, err := C.grantpt(fd); err != nil { | ||||
| 		C.close(fd) | ||||
| 		return nil, fmt.Errorf("grantpt: %w", err) | ||||
| 	} | ||||
| 	return os.NewFile(uintptr(fd), ""), nil | ||||
| } | ||||
							
								
								
									
										37
									
								
								vendor/github.com/containerd/console/pty_freebsd_nocgo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/containerd/console/pty_freebsd_nocgo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,37 +0,0 @@ | ||||
| //go:build freebsd && !cgo | ||||
| // +build freebsd,!cgo | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| // | ||||
| // Implementing the functions below requires cgo support.  Non-cgo stubs | ||||
| // versions are defined below to enable cross-compilation of source code | ||||
| // that depends on these functions, but the resultant cross-compiled | ||||
| // binaries cannot actually be used.  If the stub function(s) below are | ||||
| // actually invoked they will display an error message and cause the | ||||
| // calling process to exit. | ||||
| // | ||||
|  | ||||
| func openpt() (*os.File, error) { | ||||
| 	panic("openpt() support requires cgo.") | ||||
| } | ||||
							
								
								
									
										31
									
								
								vendor/github.com/containerd/console/pty_unix.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										31
									
								
								vendor/github.com/containerd/console/pty_unix.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,31 +0,0 @@ | ||||
| //go:build darwin || linux || netbsd || openbsd | ||||
| // +build darwin linux netbsd openbsd | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| // openpt allocates a new pseudo-terminal by opening the /dev/ptmx device | ||||
| func openpt() (*os.File, error) { | ||||
| 	return os.OpenFile("/dev/ptmx", unix.O_RDWR|unix.O_NOCTTY|unix.O_CLOEXEC, 0) | ||||
| } | ||||
							
								
								
									
										43
									
								
								vendor/github.com/containerd/console/pty_zos.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										43
									
								
								vendor/github.com/containerd/console/pty_zos.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,43 +0,0 @@ | ||||
| //go:build zos | ||||
| // +build zos | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| // openpt allocates a new pseudo-terminal by opening the first available /dev/ptypXX device | ||||
| func openpt() (*os.File, error) { | ||||
| 	var f *os.File | ||||
| 	var err error | ||||
| 	for i := 0; ; i++ { | ||||
| 		ptyp := fmt.Sprintf("/dev/ptyp%04d", i) | ||||
| 		f, err = os.OpenFile(ptyp, os.O_RDWR, 0600) | ||||
| 		if err == nil { | ||||
| 			break | ||||
| 		} | ||||
| 		if os.IsNotExist(err) { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		// else probably Resource Busy | ||||
| 	} | ||||
| 	return f, nil | ||||
| } | ||||
							
								
								
									
										44
									
								
								vendor/github.com/containerd/console/tc_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										44
									
								
								vendor/github.com/containerd/console/tc_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,44 +0,0 @@ | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	cmdTcGet = unix.TIOCGETA | ||||
| 	cmdTcSet = unix.TIOCSETA | ||||
| ) | ||||
|  | ||||
| // unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f. | ||||
| // unlockpt should be called before opening the slave side of a pty. | ||||
| func unlockpt(f *os.File) error { | ||||
| 	return unix.IoctlSetPointerInt(int(f.Fd()), unix.TIOCPTYUNLK, 0) | ||||
| } | ||||
|  | ||||
| // ptsname retrieves the name of the first available pts for the given master. | ||||
| func ptsname(f *os.File) (string, error) { | ||||
| 	n, err := unix.IoctlGetInt(int(f.Fd()), unix.TIOCPTYGNAME) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return fmt.Sprintf("/dev/pts/%d", n), nil | ||||
| } | ||||
							
								
								
									
										58
									
								
								vendor/github.com/containerd/console/tc_freebsd_cgo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										58
									
								
								vendor/github.com/containerd/console/tc_freebsd_cgo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,58 +0,0 @@ | ||||
| //go:build freebsd && cgo | ||||
| // +build freebsd,cgo | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| /* | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| */ | ||||
| import "C" | ||||
|  | ||||
| const ( | ||||
| 	cmdTcGet = unix.TIOCGETA | ||||
| 	cmdTcSet = unix.TIOCSETA | ||||
| ) | ||||
|  | ||||
| // unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f. | ||||
| // unlockpt should be called before opening the slave side of a pty. | ||||
| func unlockpt(f *os.File) error { | ||||
| 	fd := C.int(f.Fd()) | ||||
| 	if _, err := C.unlockpt(fd); err != nil { | ||||
| 		C.close(fd) | ||||
| 		return fmt.Errorf("unlockpt: %w", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ptsname retrieves the name of the first available pts for the given master. | ||||
| func ptsname(f *os.File) (string, error) { | ||||
| 	n, err := unix.IoctlGetInt(int(f.Fd()), unix.TIOCGPTN) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return fmt.Sprintf("/dev/pts/%d", n), nil | ||||
| } | ||||
							
								
								
									
										56
									
								
								vendor/github.com/containerd/console/tc_freebsd_nocgo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										56
									
								
								vendor/github.com/containerd/console/tc_freebsd_nocgo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,56 +0,0 @@ | ||||
| //go:build freebsd && !cgo | ||||
| // +build freebsd,!cgo | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	cmdTcGet = unix.TIOCGETA | ||||
| 	cmdTcSet = unix.TIOCSETA | ||||
| ) | ||||
|  | ||||
| // | ||||
| // Implementing the functions below requires cgo support.  Non-cgo stubs | ||||
| // versions are defined below to enable cross-compilation of source code | ||||
| // that depends on these functions, but the resultant cross-compiled | ||||
| // binaries cannot actually be used.  If the stub function(s) below are | ||||
| // actually invoked they will display an error message and cause the | ||||
| // calling process to exit. | ||||
| // | ||||
|  | ||||
| // unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f. | ||||
| // unlockpt should be called before opening the slave side of a pty. | ||||
| func unlockpt(f *os.File) error { | ||||
| 	panic("unlockpt() support requires cgo.") | ||||
| } | ||||
|  | ||||
| // ptsname retrieves the name of the first available pts for the given master. | ||||
| func ptsname(f *os.File) (string, error) { | ||||
| 	n, err := unix.IoctlGetInt(int(f.Fd()), unix.TIOCGPTN) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return fmt.Sprintf("/dev/pts/%d", n), nil | ||||
| } | ||||
							
								
								
									
										51
									
								
								vendor/github.com/containerd/console/tc_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										51
									
								
								vendor/github.com/containerd/console/tc_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,51 +0,0 @@ | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	cmdTcGet = unix.TCGETS | ||||
| 	cmdTcSet = unix.TCSETS | ||||
| ) | ||||
|  | ||||
| // unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f. | ||||
| // unlockpt should be called before opening the slave side of a pty. | ||||
| func unlockpt(f *os.File) error { | ||||
| 	var u int32 | ||||
| 	// XXX do not use unix.IoctlSetPointerInt here, see commit dbd69c59b81. | ||||
| 	if _, _, err := unix.Syscall(unix.SYS_IOCTL, f.Fd(), unix.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))); err != 0 { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ptsname retrieves the name of the first available pts for the given master. | ||||
| func ptsname(f *os.File) (string, error) { | ||||
| 	var u uint32 | ||||
| 	// XXX do not use unix.IoctlGetInt here, see commit dbd69c59b81. | ||||
| 	if _, _, err := unix.Syscall(unix.SYS_IOCTL, f.Fd(), unix.TIOCGPTN, uintptr(unsafe.Pointer(&u))); err != 0 { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return fmt.Sprintf("/dev/pts/%d", u), nil | ||||
| } | ||||
							
								
								
									
										45
									
								
								vendor/github.com/containerd/console/tc_netbsd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										45
									
								
								vendor/github.com/containerd/console/tc_netbsd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,45 +0,0 @@ | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"os" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	cmdTcGet = unix.TIOCGETA | ||||
| 	cmdTcSet = unix.TIOCSETA | ||||
| ) | ||||
|  | ||||
| // unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f. | ||||
| // unlockpt should be called before opening the slave side of a pty. | ||||
| // This does not exist on NetBSD, it does not allocate controlling terminals on open | ||||
| func unlockpt(f *os.File) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ptsname retrieves the name of the first available pts for the given master. | ||||
| func ptsname(f *os.File) (string, error) { | ||||
| 	ptm, err := unix.IoctlGetPtmget(int(f.Fd()), unix.TIOCPTSNAME) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return string(ptm.Sn[:bytes.IndexByte(ptm.Sn[:], 0)]), nil | ||||
| } | ||||
							
								
								
									
										52
									
								
								vendor/github.com/containerd/console/tc_openbsd_cgo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										52
									
								
								vendor/github.com/containerd/console/tc_openbsd_cgo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,52 +0,0 @@ | ||||
| //go:build openbsd && cgo | ||||
| // +build openbsd,cgo | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| //#include <stdlib.h> | ||||
| import "C" | ||||
|  | ||||
| const ( | ||||
| 	cmdTcGet = unix.TIOCGETA | ||||
| 	cmdTcSet = unix.TIOCSETA | ||||
| ) | ||||
|  | ||||
| // ptsname retrieves the name of the first available pts for the given master. | ||||
| func ptsname(f *os.File) (string, error) { | ||||
| 	ptspath, err := C.ptsname(C.int(f.Fd())) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return C.GoString(ptspath), nil | ||||
| } | ||||
|  | ||||
| // unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f. | ||||
| // unlockpt should be called before opening the slave side of a pty. | ||||
| func unlockpt(f *os.File) error { | ||||
| 	if _, err := C.grantpt(C.int(f.Fd())); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										48
									
								
								vendor/github.com/containerd/console/tc_openbsd_nocgo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								vendor/github.com/containerd/console/tc_openbsd_nocgo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,48 +0,0 @@ | ||||
| //go:build openbsd && !cgo | ||||
| // +build openbsd,!cgo | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| // | ||||
| // Implementing the functions below requires cgo support.  Non-cgo stubs | ||||
| // versions are defined below to enable cross-compilation of source code | ||||
| // that depends on these functions, but the resultant cross-compiled | ||||
| // binaries cannot actually be used.  If the stub function(s) below are | ||||
| // actually invoked they will display an error message and cause the | ||||
| // calling process to exit. | ||||
| // | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	cmdTcGet = unix.TIOCGETA | ||||
| 	cmdTcSet = unix.TIOCSETA | ||||
| ) | ||||
|  | ||||
| func ptsname(f *os.File) (string, error) { | ||||
| 	panic("ptsname() support requires cgo.") | ||||
| } | ||||
|  | ||||
| func unlockpt(f *os.File) error { | ||||
| 	panic("unlockpt() support requires cgo.") | ||||
| } | ||||
							
								
								
									
										92
									
								
								vendor/github.com/containerd/console/tc_unix.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										92
									
								
								vendor/github.com/containerd/console/tc_unix.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,92 +0,0 @@ | ||||
| //go:build darwin || freebsd || linux || netbsd || openbsd || zos | ||||
| // +build darwin freebsd linux netbsd openbsd zos | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| func tcget(fd uintptr, p *unix.Termios) error { | ||||
| 	termios, err := unix.IoctlGetTermios(int(fd), cmdTcGet) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	*p = *termios | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func tcset(fd uintptr, p *unix.Termios) error { | ||||
| 	return unix.IoctlSetTermios(int(fd), cmdTcSet, p) | ||||
| } | ||||
|  | ||||
| func tcgwinsz(fd uintptr) (WinSize, error) { | ||||
| 	var ws WinSize | ||||
|  | ||||
| 	uws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ) | ||||
| 	if err != nil { | ||||
| 		return ws, err | ||||
| 	} | ||||
|  | ||||
| 	// Translate from unix.Winsize to console.WinSize | ||||
| 	ws.Height = uws.Row | ||||
| 	ws.Width = uws.Col | ||||
| 	ws.x = uws.Xpixel | ||||
| 	ws.y = uws.Ypixel | ||||
| 	return ws, nil | ||||
| } | ||||
|  | ||||
| func tcswinsz(fd uintptr, ws WinSize) error { | ||||
| 	// Translate from console.WinSize to unix.Winsize | ||||
|  | ||||
| 	var uws unix.Winsize | ||||
| 	uws.Row = ws.Height | ||||
| 	uws.Col = ws.Width | ||||
| 	uws.Xpixel = ws.x | ||||
| 	uws.Ypixel = ws.y | ||||
|  | ||||
| 	return unix.IoctlSetWinsize(int(fd), unix.TIOCSWINSZ, &uws) | ||||
| } | ||||
|  | ||||
| func setONLCR(fd uintptr, enable bool) error { | ||||
| 	var termios unix.Termios | ||||
| 	if err := tcget(fd, &termios); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if enable { | ||||
| 		// Set +onlcr so we can act like a real terminal | ||||
| 		termios.Oflag |= unix.ONLCR | ||||
| 	} else { | ||||
| 		// Set -onlcr so we don't have to deal with \r. | ||||
| 		termios.Oflag &^= unix.ONLCR | ||||
| 	} | ||||
| 	return tcset(fd, &termios) | ||||
| } | ||||
|  | ||||
| func cfmakeraw(t unix.Termios) unix.Termios { | ||||
| 	t.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON) | ||||
| 	t.Oflag &^= unix.OPOST | ||||
| 	t.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN) | ||||
| 	t.Cflag &^= (unix.CSIZE | unix.PARENB) | ||||
| 	t.Cflag |= unix.CS8 | ||||
| 	t.Cc[unix.VMIN] = 1 | ||||
| 	t.Cc[unix.VTIME] = 0 | ||||
|  | ||||
| 	return t | ||||
| } | ||||
							
								
								
									
										39
									
								
								vendor/github.com/containerd/console/tc_zos.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/containerd/console/tc_zos.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,39 +0,0 @@ | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package console | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| 	"strings" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	cmdTcGet = unix.TCGETS | ||||
| 	cmdTcSet = unix.TCSETS | ||||
| ) | ||||
|  | ||||
| // unlockpt is a no-op on zos. | ||||
| func unlockpt(_ *os.File) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ptsname retrieves the name of the first available pts for the given master. | ||||
| func ptsname(f *os.File) (string, error) { | ||||
| 	return "/dev/ttyp" + strings.TrimPrefix(f.Name(), "/dev/ptyp"), nil | ||||
| } | ||||
							
								
								
									
										35
									
								
								vendor/github.com/google/cadvisor/container/libcontainer/handler.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								vendor/github.com/google/cadvisor/container/libcontainer/handler.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -28,7 +28,6 @@ import ( | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer" | ||||
| 	"github.com/opencontainers/runc/libcontainer/cgroups" | ||||
| 	"github.com/opencontainers/runc/libcontainer/cgroups/fs2" | ||||
| 	"k8s.io/klog/v2" | ||||
| @@ -89,10 +88,7 @@ func (h *Handler) GetStats() (*info.ContainerStats, error) { | ||||
| 		} | ||||
| 		klog.V(4).Infof("Ignoring errors when gathering stats for root cgroup since some controllers don't have stats on the root cgroup: %v", err) | ||||
| 	} | ||||
| 	libcontainerStats := &libcontainer.Stats{ | ||||
| 		CgroupStats: cgroupStats, | ||||
| 	} | ||||
| 	stats := newContainerStats(libcontainerStats, h.includedMetrics) | ||||
| 	stats := newContainerStats(cgroupStats, h.includedMetrics) | ||||
|  | ||||
| 	if h.includedMetrics.Has(container.ProcessSchedulerMetrics) { | ||||
| 		stats.Cpu.Schedstat, err = h.schedulerStatsFromProcs() | ||||
| @@ -888,28 +884,6 @@ func setHugepageStats(s *cgroups.Stats, ret *info.ContainerStats) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func setNetworkStats(libcontainerStats *libcontainer.Stats, ret *info.ContainerStats) { | ||||
| 	ret.Network.Interfaces = make([]info.InterfaceStats, len(libcontainerStats.Interfaces)) | ||||
| 	for i := range libcontainerStats.Interfaces { | ||||
| 		ret.Network.Interfaces[i] = info.InterfaceStats{ | ||||
| 			Name:      libcontainerStats.Interfaces[i].Name, | ||||
| 			RxBytes:   libcontainerStats.Interfaces[i].RxBytes, | ||||
| 			RxPackets: libcontainerStats.Interfaces[i].RxPackets, | ||||
| 			RxErrors:  libcontainerStats.Interfaces[i].RxErrors, | ||||
| 			RxDropped: libcontainerStats.Interfaces[i].RxDropped, | ||||
| 			TxBytes:   libcontainerStats.Interfaces[i].TxBytes, | ||||
| 			TxPackets: libcontainerStats.Interfaces[i].TxPackets, | ||||
| 			TxErrors:  libcontainerStats.Interfaces[i].TxErrors, | ||||
| 			TxDropped: libcontainerStats.Interfaces[i].TxDropped, | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Add to base struct for backwards compatibility. | ||||
| 	if len(ret.Network.Interfaces) > 0 { | ||||
| 		ret.Network.InterfaceStats = ret.Network.Interfaces[0] | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // read from pids path not cpu | ||||
| func setThreadsStats(s *cgroups.Stats, ret *info.ContainerStats) { | ||||
| 	if s != nil { | ||||
| @@ -918,12 +892,12 @@ func setThreadsStats(s *cgroups.Stats, ret *info.ContainerStats) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func newContainerStats(libcontainerStats *libcontainer.Stats, includedMetrics container.MetricSet) *info.ContainerStats { | ||||
| func newContainerStats(cgroupStats *cgroups.Stats, includedMetrics container.MetricSet) *info.ContainerStats { | ||||
| 	ret := &info.ContainerStats{ | ||||
| 		Timestamp: time.Now(), | ||||
| 	} | ||||
|  | ||||
| 	if s := libcontainerStats.CgroupStats; s != nil { | ||||
| 	if s := cgroupStats; s != nil { | ||||
| 		setCPUStats(s, ret, includedMetrics.Has(container.PerCpuUsageMetrics)) | ||||
| 		if includedMetrics.Has(container.DiskIOMetrics) { | ||||
| 			setDiskIoStats(s, ret) | ||||
| @@ -939,8 +913,5 @@ func newContainerStats(libcontainerStats *libcontainer.Stats, includedMetrics co | ||||
| 			setCPUSetStats(s, ret) | ||||
| 		} | ||||
| 	} | ||||
| 	if len(libcontainerStats.Interfaces) > 0 { | ||||
| 		setNetworkStats(libcontainerStats, ret) | ||||
| 	} | ||||
| 	return ret | ||||
| } | ||||
|   | ||||
							
								
								
									
										6
									
								
								vendor/github.com/google/cadvisor/utils/sysfs/sysfs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/google/cadvisor/utils/sysfs/sysfs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -254,10 +254,8 @@ func (fs *realSysFs) IsBlockDeviceHidden(name string) (bool, error) { | ||||
| 	if err != nil { | ||||
| 		return false, fmt.Errorf("failed to read %s: %w", devHiddenPath, err) | ||||
| 	} | ||||
| 	if string(hidden) == "1" { | ||||
| 		return true, nil | ||||
| 	} | ||||
| 	return false, nil | ||||
|  | ||||
| 	return strings.TrimSpace(string(hidden)) == "1", nil | ||||
| } | ||||
|  | ||||
| func (fs *realSysFs) GetBlockDeviceScheduler(name string) (string, error) { | ||||
|   | ||||
							
								
								
									
										318
									
								
								vendor/github.com/opencontainers/runc/libcontainer/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										318
									
								
								vendor/github.com/opencontainers/runc/libcontainer/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,318 +0,0 @@ | ||||
| # libcontainer | ||||
|  | ||||
| [](https://pkg.go.dev/github.com/opencontainers/runc/libcontainer) | ||||
|  | ||||
| Libcontainer provides a native Go implementation for creating containers | ||||
| with namespaces, cgroups, capabilities, and filesystem access controls. | ||||
| It allows you to manage the lifecycle of the container performing additional operations | ||||
| after the container is created. | ||||
|  | ||||
|  | ||||
| #### Container | ||||
| A container is a self contained execution environment that shares the kernel of the | ||||
| host system and which is (optionally) isolated from other containers in the system. | ||||
|  | ||||
| #### Using libcontainer | ||||
|  | ||||
| Because containers are spawned in a two step process you will need a binary that | ||||
| will be executed as the init process for the container. In libcontainer, we use | ||||
| the current binary (/proc/self/exe) to be executed as the init process, and use | ||||
| arg "init", we call the first step process "bootstrap", so you always need a "init" | ||||
| function as the entry of "bootstrap". | ||||
|  | ||||
| In addition to the go init function the early stage bootstrap is handled by importing | ||||
| [nsenter](https://github.com/opencontainers/runc/blob/master/libcontainer/nsenter/README.md). | ||||
|  | ||||
| ```go | ||||
| import ( | ||||
| 	_ "github.com/opencontainers/runc/libcontainer/nsenter" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	if len(os.Args) > 1 && os.Args[1] == "init" { | ||||
| 		runtime.GOMAXPROCS(1) | ||||
| 		runtime.LockOSThread() | ||||
| 		factory, _ := libcontainer.New("") | ||||
| 		if err := factory.StartInitialization(); err != nil { | ||||
| 			logrus.Fatal(err) | ||||
| 		} | ||||
| 		panic("--this line should have never been executed, congratulations--") | ||||
| 	} | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Then to create a container you first have to initialize an instance of a factory | ||||
| that will handle the creation and initialization for a container. | ||||
|  | ||||
| ```go | ||||
| factory, err := libcontainer.New("/var/lib/container", libcontainer.Cgroupfs, libcontainer.InitArgs(os.Args[0], "init")) | ||||
| if err != nil { | ||||
| 	logrus.Fatal(err) | ||||
| 	return | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Once you have an instance of the factory created we can create a configuration | ||||
| struct describing how the container is to be created. A sample would look similar to this: | ||||
|  | ||||
| ```go | ||||
| defaultMountFlags := unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV | ||||
| var devices []*configs.DeviceRule | ||||
| for _, device := range specconv.AllowedDevices { | ||||
| 	devices = append(devices, &device.Rule) | ||||
| } | ||||
| config := &configs.Config{ | ||||
| 	Rootfs: "/your/path/to/rootfs", | ||||
| 	Capabilities: &configs.Capabilities{ | ||||
| 		Bounding: []string{ | ||||
| 			"CAP_CHOWN", | ||||
| 			"CAP_DAC_OVERRIDE", | ||||
| 			"CAP_FSETID", | ||||
| 			"CAP_FOWNER", | ||||
| 			"CAP_MKNOD", | ||||
| 			"CAP_NET_RAW", | ||||
| 			"CAP_SETGID", | ||||
| 			"CAP_SETUID", | ||||
| 			"CAP_SETFCAP", | ||||
| 			"CAP_SETPCAP", | ||||
| 			"CAP_NET_BIND_SERVICE", | ||||
| 			"CAP_SYS_CHROOT", | ||||
| 			"CAP_KILL", | ||||
| 			"CAP_AUDIT_WRITE", | ||||
| 		}, | ||||
| 		Effective: []string{ | ||||
| 			"CAP_CHOWN", | ||||
| 			"CAP_DAC_OVERRIDE", | ||||
| 			"CAP_FSETID", | ||||
| 			"CAP_FOWNER", | ||||
| 			"CAP_MKNOD", | ||||
| 			"CAP_NET_RAW", | ||||
| 			"CAP_SETGID", | ||||
| 			"CAP_SETUID", | ||||
| 			"CAP_SETFCAP", | ||||
| 			"CAP_SETPCAP", | ||||
| 			"CAP_NET_BIND_SERVICE", | ||||
| 			"CAP_SYS_CHROOT", | ||||
| 			"CAP_KILL", | ||||
| 			"CAP_AUDIT_WRITE", | ||||
| 		}, | ||||
| 		Permitted: []string{ | ||||
| 			"CAP_CHOWN", | ||||
| 			"CAP_DAC_OVERRIDE", | ||||
| 			"CAP_FSETID", | ||||
| 			"CAP_FOWNER", | ||||
| 			"CAP_MKNOD", | ||||
| 			"CAP_NET_RAW", | ||||
| 			"CAP_SETGID", | ||||
| 			"CAP_SETUID", | ||||
| 			"CAP_SETFCAP", | ||||
| 			"CAP_SETPCAP", | ||||
| 			"CAP_NET_BIND_SERVICE", | ||||
| 			"CAP_SYS_CHROOT", | ||||
| 			"CAP_KILL", | ||||
| 			"CAP_AUDIT_WRITE", | ||||
| 		}, | ||||
| 		Ambient: []string{ | ||||
| 			"CAP_CHOWN", | ||||
| 			"CAP_DAC_OVERRIDE", | ||||
| 			"CAP_FSETID", | ||||
| 			"CAP_FOWNER", | ||||
| 			"CAP_MKNOD", | ||||
| 			"CAP_NET_RAW", | ||||
| 			"CAP_SETGID", | ||||
| 			"CAP_SETUID", | ||||
| 			"CAP_SETFCAP", | ||||
| 			"CAP_SETPCAP", | ||||
| 			"CAP_NET_BIND_SERVICE", | ||||
| 			"CAP_SYS_CHROOT", | ||||
| 			"CAP_KILL", | ||||
| 			"CAP_AUDIT_WRITE", | ||||
| 		}, | ||||
| 	}, | ||||
| 	Namespaces: configs.Namespaces([]configs.Namespace{ | ||||
| 		{Type: configs.NEWNS}, | ||||
| 		{Type: configs.NEWUTS}, | ||||
| 		{Type: configs.NEWIPC}, | ||||
| 		{Type: configs.NEWPID}, | ||||
| 		{Type: configs.NEWUSER}, | ||||
| 		{Type: configs.NEWNET}, | ||||
| 		{Type: configs.NEWCGROUP}, | ||||
| 	}), | ||||
| 	Cgroups: &configs.Cgroup{ | ||||
| 		Name:   "test-container", | ||||
| 		Parent: "system", | ||||
| 		Resources: &configs.Resources{ | ||||
| 			MemorySwappiness: nil, | ||||
| 			Devices:          devices, | ||||
| 		}, | ||||
| 	}, | ||||
| 	MaskPaths: []string{ | ||||
| 		"/proc/kcore", | ||||
| 		"/sys/firmware", | ||||
| 	}, | ||||
| 	ReadonlyPaths: []string{ | ||||
| 		"/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus", | ||||
| 	}, | ||||
| 	Devices:  specconv.AllowedDevices, | ||||
| 	Hostname: "testing", | ||||
| 	Mounts: []*configs.Mount{ | ||||
| 		{ | ||||
| 			Source:      "proc", | ||||
| 			Destination: "/proc", | ||||
| 			Device:      "proc", | ||||
| 			Flags:       defaultMountFlags, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Source:      "tmpfs", | ||||
| 			Destination: "/dev", | ||||
| 			Device:      "tmpfs", | ||||
| 			Flags:       unix.MS_NOSUID | unix.MS_STRICTATIME, | ||||
| 			Data:        "mode=755", | ||||
| 		}, | ||||
| 		{ | ||||
| 			Source:      "devpts", | ||||
| 			Destination: "/dev/pts", | ||||
| 			Device:      "devpts", | ||||
| 			Flags:       unix.MS_NOSUID | unix.MS_NOEXEC, | ||||
| 			Data:        "newinstance,ptmxmode=0666,mode=0620,gid=5", | ||||
| 		}, | ||||
| 		{ | ||||
| 			Device:      "tmpfs", | ||||
| 			Source:      "shm", | ||||
| 			Destination: "/dev/shm", | ||||
| 			Data:        "mode=1777,size=65536k", | ||||
| 			Flags:       defaultMountFlags, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Source:      "mqueue", | ||||
| 			Destination: "/dev/mqueue", | ||||
| 			Device:      "mqueue", | ||||
| 			Flags:       defaultMountFlags, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Source:      "sysfs", | ||||
| 			Destination: "/sys", | ||||
| 			Device:      "sysfs", | ||||
| 			Flags:       defaultMountFlags | unix.MS_RDONLY, | ||||
| 		}, | ||||
| 	}, | ||||
| 	UidMappings: []configs.IDMap{ | ||||
| 		{ | ||||
| 			ContainerID: 0, | ||||
| 			HostID: 1000, | ||||
| 			Size: 65536, | ||||
| 		}, | ||||
| 	}, | ||||
| 	GidMappings: []configs.IDMap{ | ||||
| 		{ | ||||
| 			ContainerID: 0, | ||||
| 			HostID: 1000, | ||||
| 			Size: 65536, | ||||
| 		}, | ||||
| 	}, | ||||
| 	Networks: []*configs.Network{ | ||||
| 		{ | ||||
| 			Type:    "loopback", | ||||
| 			Address: "127.0.0.1/0", | ||||
| 			Gateway: "localhost", | ||||
| 		}, | ||||
| 	}, | ||||
| 	Rlimits: []configs.Rlimit{ | ||||
| 		{ | ||||
| 			Type: unix.RLIMIT_NOFILE, | ||||
| 			Hard: uint64(1025), | ||||
| 			Soft: uint64(1025), | ||||
| 		}, | ||||
| 	}, | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Once you have the configuration populated you can create a container: | ||||
|  | ||||
| ```go | ||||
| container, err := factory.Create("container-id", config) | ||||
| if err != nil { | ||||
| 	logrus.Fatal(err) | ||||
| 	return | ||||
| } | ||||
| ``` | ||||
|  | ||||
| To spawn bash as the initial process inside the container and have the | ||||
| processes pid returned in order to wait, signal, or kill the process: | ||||
|  | ||||
| ```go | ||||
| process := &libcontainer.Process{ | ||||
| 	Args:   []string{"/bin/bash"}, | ||||
| 	Env:    []string{"PATH=/bin"}, | ||||
| 	User:   "daemon", | ||||
| 	Stdin:  os.Stdin, | ||||
| 	Stdout: os.Stdout, | ||||
| 	Stderr: os.Stderr, | ||||
| 	Init:   true, | ||||
| } | ||||
|  | ||||
| err := container.Run(process) | ||||
| if err != nil { | ||||
| 	container.Destroy() | ||||
| 	logrus.Fatal(err) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // wait for the process to finish. | ||||
| _, err := process.Wait() | ||||
| if err != nil { | ||||
| 	logrus.Fatal(err) | ||||
| } | ||||
|  | ||||
| // destroy the container. | ||||
| container.Destroy() | ||||
| ``` | ||||
|  | ||||
| Additional ways to interact with a running container are: | ||||
|  | ||||
| ```go | ||||
| // return all the pids for all processes running inside the container. | ||||
| processes, err := container.Processes() | ||||
|  | ||||
| // get detailed cpu, memory, io, and network statistics for the container and | ||||
| // it's processes. | ||||
| stats, err := container.Stats() | ||||
|  | ||||
| // pause all processes inside the container. | ||||
| container.Pause() | ||||
|  | ||||
| // resume all paused processes. | ||||
| container.Resume() | ||||
|  | ||||
| // send signal to container's init process. | ||||
| container.Signal(signal) | ||||
|  | ||||
| // update container resource constraints. | ||||
| container.Set(config) | ||||
|  | ||||
| // get current status of the container. | ||||
| status, err := container.Status() | ||||
|  | ||||
| // get current container's state information. | ||||
| state, err := container.State() | ||||
| ``` | ||||
|  | ||||
|  | ||||
| #### Checkpoint & Restore | ||||
|  | ||||
| libcontainer now integrates [CRIU](http://criu.org/) for checkpointing and restoring containers. | ||||
| This lets you save the state of a process running inside a container to disk, and then restore | ||||
| that state into a new process, on the same machine or on another machine. | ||||
|  | ||||
| `criu` version 1.5.2 or higher is required to use checkpoint and restore. | ||||
| If you don't already  have `criu` installed, you can build it from source, following the | ||||
| [online instructions](http://criu.org/Installation). `criu` is also installed in the docker image | ||||
| generated when building libcontainer with docker. | ||||
|  | ||||
|  | ||||
| ## Copyright and license | ||||
|  | ||||
| Code and documentation copyright 2014 Docker, inc. | ||||
| The code and documentation are released under the [Apache 2.0 license](../LICENSE). | ||||
| The documentation is also released under Creative Commons Attribution 4.0 International License. | ||||
| You may obtain a copy of the license, titled CC-BY-4.0, at http://creativecommons.org/licenses/by/4.0/. | ||||
							
								
								
									
										465
									
								
								vendor/github.com/opencontainers/runc/libcontainer/SPEC.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										465
									
								
								vendor/github.com/opencontainers/runc/libcontainer/SPEC.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,465 +0,0 @@ | ||||
| ## Container Specification - v1 | ||||
|  | ||||
| This is the standard configuration for version 1 containers.  It includes | ||||
| namespaces, standard filesystem setup, a default Linux capability set, and | ||||
| information about resource reservations.  It also has information about any  | ||||
| populated environment settings for the processes running inside a container. | ||||
|  | ||||
| Along with the configuration of how a container is created the standard also | ||||
| discusses actions that can be performed on a container to manage and inspect | ||||
| information about the processes running inside. | ||||
|  | ||||
| The v1 profile is meant to be able to accommodate the majority of applications | ||||
| with a strong security configuration. | ||||
|  | ||||
| ### System Requirements and Compatibility | ||||
|  | ||||
| Minimum requirements: | ||||
| * Kernel version - 3.10 recommended 2.6.2x minimum(with backported patches) | ||||
| * Mounted cgroups with each subsystem in its own hierarchy | ||||
|  | ||||
|  | ||||
| ### Namespaces | ||||
|  | ||||
| |     Flag        | Enabled | | ||||
| | --------------- | ------- | | ||||
| | CLONE_NEWPID    |    1    | | ||||
| | CLONE_NEWUTS    |    1    | | ||||
| | CLONE_NEWIPC    |    1    | | ||||
| | CLONE_NEWNET    |    1    | | ||||
| | CLONE_NEWNS     |    1    | | ||||
| | CLONE_NEWUSER   |    1    | | ||||
| | CLONE_NEWCGROUP |    1    | | ||||
|  | ||||
| Namespaces are created for the container via the `unshare` syscall. | ||||
|  | ||||
|  | ||||
| ### Filesystem | ||||
|  | ||||
| A root filesystem must be provided to a container for execution.  The container | ||||
| will use this root filesystem (rootfs) to jail and spawn processes inside where | ||||
| the binaries and system libraries are local to that directory.  Any binaries | ||||
| to be executed must be contained within this rootfs. | ||||
|  | ||||
| Mounts that happen inside the container are automatically cleaned up when the | ||||
| container exits as the mount namespace is destroyed and the kernel will  | ||||
| unmount all the mounts that were setup within that namespace. | ||||
|  | ||||
| For a container to execute properly there are certain filesystems that  | ||||
| are required to be mounted within the rootfs that the runtime will setup. | ||||
|  | ||||
| |     Path    |  Type  |                  Flags                 |                 Data                     | | ||||
| | ----------- | ------ | -------------------------------------- | ---------------------------------------- | | ||||
| | /proc       | proc   | MS_NOEXEC,MS_NOSUID,MS_NODEV           |                                          | | ||||
| | /dev        | tmpfs  | MS_NOEXEC,MS_STRICTATIME               | mode=755                                 | | ||||
| | /dev/shm    | tmpfs  | MS_NOEXEC,MS_NOSUID,MS_NODEV           | mode=1777,size=65536k                    | | ||||
| | /dev/mqueue | mqueue | MS_NOEXEC,MS_NOSUID,MS_NODEV           |                                          | | ||||
| | /dev/pts    | devpts | MS_NOEXEC,MS_NOSUID                    | newinstance,ptmxmode=0666,mode=620,gid=5 | | ||||
| | /sys        | sysfs  | MS_NOEXEC,MS_NOSUID,MS_NODEV,MS_RDONLY |                                          | | ||||
|  | ||||
|  | ||||
| After a container's filesystems are mounted within the newly created  | ||||
| mount namespace `/dev` will need to be populated with a set of device nodes. | ||||
| It is expected that a rootfs does not need to have any device nodes specified | ||||
| for `/dev` within the rootfs as the container will setup the correct devices | ||||
| that are required for executing a container's process. | ||||
|  | ||||
| |      Path    | Mode |   Access   | | ||||
| | ------------ | ---- | ---------- | | ||||
| | /dev/null    | 0666 |  rwm       | | ||||
| | /dev/zero    | 0666 |  rwm       | | ||||
| | /dev/full    | 0666 |  rwm       | | ||||
| | /dev/tty     | 0666 |  rwm       | | ||||
| | /dev/random  | 0666 |  rwm       | | ||||
| | /dev/urandom | 0666 |  rwm       | | ||||
|  | ||||
|  | ||||
| **ptmx** | ||||
| `/dev/ptmx` will need to be a symlink to the host's `/dev/ptmx` within | ||||
| the container.   | ||||
|  | ||||
| The use of a pseudo TTY is optional within a container and it should support both. | ||||
| If a pseudo is provided to the container `/dev/console` will need to be  | ||||
| setup by binding the console in `/dev/` after it has been populated and mounted | ||||
| in tmpfs. | ||||
|  | ||||
| |      Source     | Destination  | UID GID | Mode | Type | | ||||
| | --------------- | ------------ | ------- | ---- | ---- | | ||||
| | *pty host path* | /dev/console | 0 0     | 0600 | bind |  | ||||
|  | ||||
|  | ||||
| After `/dev/null` has been setup we check for any external links between | ||||
| the container's io, STDIN, STDOUT, STDERR.  If the container's io is pointing | ||||
| to `/dev/null` outside the container we close and `dup2` the `/dev/null`  | ||||
| that is local to the container's rootfs. | ||||
|  | ||||
|  | ||||
| After the container has `/proc` mounted a few standard symlinks are setup  | ||||
| within `/dev/` for the io. | ||||
|  | ||||
| |    Source       | Destination | | ||||
| | --------------- | ----------- | | ||||
| | /proc/self/fd   | /dev/fd     | | ||||
| | /proc/self/fd/0 | /dev/stdin  | | ||||
| | /proc/self/fd/1 | /dev/stdout | | ||||
| | /proc/self/fd/2 | /dev/stderr | | ||||
|  | ||||
| A `pivot_root` is used to change the root for the process, effectively  | ||||
| jailing the process inside the rootfs. | ||||
|  | ||||
| ```c | ||||
| put_old = mkdir(...); | ||||
| pivot_root(rootfs, put_old); | ||||
| chdir("/"); | ||||
| unmount(put_old, MS_DETACH); | ||||
| rmdir(put_old); | ||||
| ``` | ||||
|  | ||||
| For container's running with a rootfs inside `ramfs` a `MS_MOVE` combined | ||||
| with a `chroot` is required as `pivot_root` is not supported in `ramfs`. | ||||
|  | ||||
| ```c | ||||
| mount(rootfs, "/", NULL, MS_MOVE, NULL); | ||||
| chroot("."); | ||||
| chdir("/"); | ||||
| ``` | ||||
|  | ||||
| The `umask` is set back to `0022` after the filesystem setup has been completed. | ||||
|  | ||||
| ### Resources | ||||
|  | ||||
| Cgroups are used to handle resource allocation for containers.  This includes | ||||
| system resources like cpu, memory, and device access. | ||||
|  | ||||
| | Subsystem  | Enabled | | ||||
| | ---------- | ------- | | ||||
| | devices    | 1       | | ||||
| | memory     | 1       | | ||||
| | cpu        | 1       | | ||||
| | cpuacct    | 1       | | ||||
| | cpuset     | 1       | | ||||
| | blkio      | 1       | | ||||
| | perf_event | 1       | | ||||
| | freezer    | 1       | | ||||
| | hugetlb    | 1       | | ||||
| | pids       | 1       | | ||||
|  | ||||
|  | ||||
| All cgroup subsystem are joined so that statistics can be collected from | ||||
| each of the subsystems.  Freezer does not expose any stats but is joined | ||||
| so that containers can be paused and resumed. | ||||
|  | ||||
| The parent process of the container's init must place the init pid inside | ||||
| the correct cgroups before the initialization begins.  This is done so | ||||
| that no processes or threads escape the cgroups.  This sync is  | ||||
| done via a pipe ( specified in the runtime section below ) that the container's | ||||
| init process will block waiting for the parent to finish setup. | ||||
|  | ||||
| ### IntelRdt | ||||
|  | ||||
| Intel platforms with new Xeon CPU support Resource Director Technology (RDT). | ||||
| Cache Allocation Technology (CAT) and Memory Bandwidth Allocation (MBA) are | ||||
| two sub-features of RDT. | ||||
|  | ||||
| Cache Allocation Technology (CAT) provides a way for the software to restrict | ||||
| cache allocation to a defined 'subset' of L3 cache which may be overlapping | ||||
| with other 'subsets'. The different subsets are identified by class of | ||||
| service (CLOS) and each CLOS has a capacity bitmask (CBM). | ||||
|  | ||||
| Memory Bandwidth Allocation (MBA) provides indirect and approximate throttle | ||||
| over memory bandwidth for the software. A user controls the resource by | ||||
| indicating the percentage of maximum memory bandwidth or memory bandwidth limit | ||||
| in MBps unit if MBA Software Controller is enabled. | ||||
|  | ||||
| It can be used to handle L3 cache and memory bandwidth resources allocation | ||||
| for containers if hardware and kernel support Intel RDT CAT and MBA features. | ||||
|  | ||||
| In Linux 4.10 kernel or newer, the interface is defined and exposed via | ||||
| "resource control" filesystem, which is a "cgroup-like" interface. | ||||
|  | ||||
| Comparing with cgroups, it has similar process management lifecycle and | ||||
| interfaces in a container. But unlike cgroups' hierarchy, it has single level | ||||
| filesystem layout. | ||||
|  | ||||
| CAT and MBA features are introduced in Linux 4.10 and 4.12 kernel via | ||||
| "resource control" filesystem. | ||||
|  | ||||
| Intel RDT "resource control" filesystem hierarchy: | ||||
| ``` | ||||
| mount -t resctrl resctrl /sys/fs/resctrl | ||||
| tree /sys/fs/resctrl | ||||
| /sys/fs/resctrl/ | ||||
| |-- info | ||||
| |   |-- L3 | ||||
| |   |   |-- cbm_mask | ||||
| |   |   |-- min_cbm_bits | ||||
| |   |   |-- num_closids | ||||
| |   |-- MB | ||||
| |       |-- bandwidth_gran | ||||
| |       |-- delay_linear | ||||
| |       |-- min_bandwidth | ||||
| |       |-- num_closids | ||||
| |-- ... | ||||
| |-- schemata | ||||
| |-- tasks | ||||
| |-- <container_id> | ||||
|     |-- ... | ||||
|     |-- schemata | ||||
|     |-- tasks | ||||
| ``` | ||||
|  | ||||
| For runc, we can make use of `tasks` and `schemata` configuration for L3 | ||||
| cache and memory bandwidth resources constraints. | ||||
|  | ||||
| The file `tasks` has a list of tasks that belongs to this group (e.g., | ||||
| <container_id>" group). Tasks can be added to a group by writing the task ID | ||||
| to the "tasks" file (which will automatically remove them from the previous | ||||
| group to which they belonged). New tasks created by fork(2) and clone(2) are | ||||
| added to the same group as their parent. | ||||
|  | ||||
| The file `schemata` has a list of all the resources available to this group. | ||||
| Each resource (L3 cache, memory bandwidth) has its own line and format. | ||||
|  | ||||
| L3 cache schema: | ||||
| It has allocation bitmasks/values for L3 cache on each socket, which | ||||
| contains L3 cache id and capacity bitmask (CBM). | ||||
| ``` | ||||
| 	Format: "L3:<cache_id0>=<cbm0>;<cache_id1>=<cbm1>;..." | ||||
| ``` | ||||
| For example, on a two-socket machine, the schema line could be "L3:0=ff;1=c0" | ||||
| which means L3 cache id 0's CBM is 0xff, and L3 cache id 1's CBM is 0xc0. | ||||
|  | ||||
| The valid L3 cache CBM is a *contiguous bits set* and number of bits that can | ||||
| be set is less than the max bit. The max bits in the CBM is varied among | ||||
| supported Intel CPU models. Kernel will check if it is valid when writing. | ||||
| e.g., default value 0xfffff in root indicates the max bits of CBM is 20 | ||||
| bits, which mapping to entire L3 cache capacity. Some valid CBM values to | ||||
| set in a group: 0xf, 0xf0, 0x3ff, 0x1f00 and etc. | ||||
|  | ||||
| Memory bandwidth schema: | ||||
| It has allocation values for memory bandwidth on each socket, which contains | ||||
| L3 cache id and memory bandwidth. | ||||
| ``` | ||||
| 	Format: "MB:<cache_id0>=bandwidth0;<cache_id1>=bandwidth1;..." | ||||
| ``` | ||||
| For example, on a two-socket machine, the schema line could be "MB:0=20;1=70" | ||||
|  | ||||
| The minimum bandwidth percentage value for each CPU model is predefined and | ||||
| can be looked up through "info/MB/min_bandwidth". The bandwidth granularity | ||||
| that is allocated is also dependent on the CPU model and can be looked up at | ||||
| "info/MB/bandwidth_gran". The available bandwidth control steps are: | ||||
| min_bw + N * bw_gran. Intermediate values are rounded to the next control | ||||
| step available on the hardware. | ||||
|  | ||||
| If MBA Software Controller is enabled through mount option "-o mba_MBps" | ||||
| mount -t resctrl resctrl -o mba_MBps /sys/fs/resctrl | ||||
| We could specify memory bandwidth in "MBps" (Mega Bytes per second) unit | ||||
| instead of "percentages". The kernel underneath would use a software feedback | ||||
| mechanism or a "Software Controller" which reads the actual bandwidth using | ||||
| MBM counters and adjust the memory bandwidth percentages to ensure: | ||||
| "actual memory bandwidth < user specified memory bandwidth". | ||||
|  | ||||
| For example, on a two-socket machine, the schema line could be | ||||
| "MB:0=5000;1=7000" which means 5000 MBps memory bandwidth limit on socket 0 | ||||
| and 7000 MBps memory bandwidth limit on socket 1. | ||||
|  | ||||
| For more information about Intel RDT kernel interface:   | ||||
| https://www.kernel.org/doc/Documentation/x86/intel_rdt_ui.txt | ||||
|  | ||||
| ``` | ||||
| An example for runc: | ||||
| Consider a two-socket machine with two L3 caches where the default CBM is | ||||
| 0x7ff and the max CBM length is 11 bits, and minimum memory bandwidth of 10% | ||||
| with a memory bandwidth granularity of 10%. | ||||
|  | ||||
| Tasks inside the container only have access to the "upper" 7/11 of L3 cache | ||||
| on socket 0 and the "lower" 5/11 L3 cache on socket 1, and may use a | ||||
| maximum memory bandwidth of 20% on socket 0 and 70% on socket 1. | ||||
|  | ||||
| "linux": { | ||||
|     "intelRdt": { | ||||
|         "closID": "guaranteed_group", | ||||
|         "l3CacheSchema": "L3:0=7f0;1=1f", | ||||
|         "memBwSchema": "MB:0=20;1=70" | ||||
|     } | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ### Security  | ||||
|  | ||||
| The standard set of Linux capabilities that are set in a container | ||||
| provide a good default for security and flexibility for the applications. | ||||
|  | ||||
|  | ||||
| |     Capability       | Enabled | | ||||
| | -------------------- | ------- | | ||||
| | CAP_NET_RAW          | 1       | | ||||
| | CAP_NET_BIND_SERVICE | 1       | | ||||
| | CAP_AUDIT_READ       | 1       | | ||||
| | CAP_AUDIT_WRITE      | 1       | | ||||
| | CAP_DAC_OVERRIDE     | 1       | | ||||
| | CAP_SETFCAP          | 1       | | ||||
| | CAP_SETPCAP          | 1       | | ||||
| | CAP_SETGID           | 1       | | ||||
| | CAP_SETUID           | 1       | | ||||
| | CAP_MKNOD            | 1       | | ||||
| | CAP_CHOWN            | 1       | | ||||
| | CAP_FOWNER           | 1       | | ||||
| | CAP_FSETID           | 1       | | ||||
| | CAP_KILL             | 1       | | ||||
| | CAP_SYS_CHROOT       | 1       | | ||||
| | CAP_NET_BROADCAST    | 0       | | ||||
| | CAP_SYS_MODULE       | 0       | | ||||
| | CAP_SYS_RAWIO        | 0       | | ||||
| | CAP_SYS_PACCT        | 0       | | ||||
| | CAP_SYS_ADMIN        | 0       | | ||||
| | CAP_SYS_NICE         | 0       | | ||||
| | CAP_SYS_RESOURCE     | 0       | | ||||
| | CAP_SYS_TIME         | 0       | | ||||
| | CAP_SYS_TTY_CONFIG   | 0       | | ||||
| | CAP_AUDIT_CONTROL    | 0       | | ||||
| | CAP_MAC_OVERRIDE     | 0       | | ||||
| | CAP_MAC_ADMIN        | 0       | | ||||
| | CAP_NET_ADMIN        | 0       | | ||||
| | CAP_SYSLOG           | 0       | | ||||
| | CAP_DAC_READ_SEARCH  | 0       | | ||||
| | CAP_LINUX_IMMUTABLE  | 0       | | ||||
| | CAP_IPC_LOCK         | 0       | | ||||
| | CAP_IPC_OWNER        | 0       | | ||||
| | CAP_SYS_PTRACE       | 0       | | ||||
| | CAP_SYS_BOOT         | 0       | | ||||
| | CAP_LEASE            | 0       | | ||||
| | CAP_WAKE_ALARM       | 0       | | ||||
| | CAP_BLOCK_SUSPEND    | 0       | | ||||
|  | ||||
|  | ||||
| Additional security layers like [apparmor](https://wiki.ubuntu.com/AppArmor) | ||||
| and [selinux](http://selinuxproject.org/page/Main_Page) can be used with | ||||
| the containers.  A container should support setting an apparmor profile or  | ||||
| selinux process and mount labels if provided in the configuration.   | ||||
|  | ||||
| Standard apparmor profile: | ||||
| ```c | ||||
| #include <tunables/global> | ||||
| profile <profile_name> flags=(attach_disconnected,mediate_deleted) { | ||||
|   #include <abstractions/base> | ||||
|   network, | ||||
|   capability, | ||||
|   file, | ||||
|   umount, | ||||
|  | ||||
|   deny @{PROC}/sys/fs/** wklx, | ||||
|   deny @{PROC}/sysrq-trigger rwklx, | ||||
|   deny @{PROC}/mem rwklx, | ||||
|   deny @{PROC}/kmem rwklx, | ||||
|   deny @{PROC}/sys/kernel/[^s][^h][^m]* wklx, | ||||
|   deny @{PROC}/sys/kernel/*/** wklx, | ||||
|  | ||||
|   deny mount, | ||||
|  | ||||
|   deny /sys/[^f]*/** wklx, | ||||
|   deny /sys/f[^s]*/** wklx, | ||||
|   deny /sys/fs/[^c]*/** wklx, | ||||
|   deny /sys/fs/c[^g]*/** wklx, | ||||
|   deny /sys/fs/cg[^r]*/** wklx, | ||||
|   deny /sys/firmware/efi/efivars/** rwklx, | ||||
|   deny /sys/kernel/security/** rwklx, | ||||
| } | ||||
| ``` | ||||
|  | ||||
| *TODO: seccomp work is being done to find a good default config* | ||||
|  | ||||
| ### Runtime and Init Process | ||||
|  | ||||
| During container creation the parent process needs to talk to the container's init  | ||||
| process and have a form of synchronization.  This is accomplished by creating | ||||
| a pipe that is passed to the container's init.  When the init process first spawns  | ||||
| it will block on its side of the pipe until the parent closes its side.  This | ||||
| allows the parent to have time to set the new process inside a cgroup hierarchy  | ||||
| and/or write any uid/gid mappings required for user namespaces.   | ||||
| The pipe is passed to the init process via FD 3. | ||||
|  | ||||
| The application consuming libcontainer should be compiled statically.  libcontainer | ||||
| does not define any init process and the arguments provided are used to `exec` the | ||||
| process inside the application.  There should be no long running init within the  | ||||
| container spec. | ||||
|  | ||||
| If a pseudo tty is provided to a container it will open and `dup2` the console | ||||
| as the container's STDIN, STDOUT, STDERR as well as mounting the console | ||||
| as `/dev/console`. | ||||
|  | ||||
| An extra set of mounts are provided to a container and setup for use.  A container's | ||||
| rootfs can contain some non portable files inside that can cause side effects during | ||||
| execution of a process.  These files are usually created and populated with the container | ||||
| specific information via the runtime.   | ||||
|  | ||||
| **Extra runtime files:** | ||||
| * /etc/hosts  | ||||
| * /etc/resolv.conf | ||||
| * /etc/hostname | ||||
| * /etc/localtime | ||||
|  | ||||
|  | ||||
| #### Defaults | ||||
|  | ||||
| There are a few defaults that can be overridden by users, but in their omission | ||||
| these apply to processes within a container. | ||||
|  | ||||
| |       Type          |             Value              | | ||||
| | ------------------- | ------------------------------ | | ||||
| | Parent Death Signal | SIGKILL                        |  | ||||
| | UID                 | 0                              | | ||||
| | GID                 | 0                              | | ||||
| | GROUPS              | 0, NULL                        | | ||||
| | CWD                 | "/"                            | | ||||
| | $HOME               | Current user's home dir or "/" | | ||||
| | Readonly rootfs     | false                          | | ||||
| | Pseudo TTY          | false                          | | ||||
|  | ||||
|  | ||||
| ## Actions | ||||
|  | ||||
| After a container is created there is a standard set of actions that can | ||||
| be done to the container.  These actions are part of the public API for  | ||||
| a container. | ||||
|  | ||||
| |     Action     |                         Description                                | | ||||
| | -------------- | ------------------------------------------------------------------ | | ||||
| | Get processes  | Return all the pids for processes running inside a container       |  | ||||
| | Get Stats      | Return resource statistics for the container as a whole            | | ||||
| | Wait           | Waits on the container's init process ( pid 1 )                    | | ||||
| | Wait Process   | Wait on any of the container's processes returning the exit status |  | ||||
| | Destroy        | Kill the container's init process and remove any filesystem state  | | ||||
| | Signal         | Send a signal to the container's init process                      | | ||||
| | Signal Process | Send a signal to any of the container's processes                  | | ||||
| | Pause          | Pause all processes inside the container                           | | ||||
| | Resume         | Resume all processes inside the container if paused                | | ||||
| | Exec           | Execute a new process inside of the container  ( requires setns )  | | ||||
| | Set            | Setup configs of the container after it's created                  | | ||||
|  | ||||
| ### Execute a new process inside of a running container | ||||
|  | ||||
| User can execute a new process inside of a running container. Any binaries to be | ||||
| executed must be accessible within the container's rootfs. | ||||
|  | ||||
| The started process will run inside the container's rootfs. Any changes | ||||
| made by the process to the container's filesystem will persist after the | ||||
| process finished executing. | ||||
|  | ||||
| The started process will join all the container's existing namespaces. When the | ||||
| container is paused, the process will also be paused and will resume when | ||||
| the container is unpaused.  The started process will only run when the container's | ||||
| primary process (PID 1) is running, and will not be restarted when the container | ||||
| is restarted. | ||||
|  | ||||
| #### Planned additions | ||||
|  | ||||
| The started process will have its own cgroups nested inside the container's | ||||
| cgroups. This is used for process tracking and optionally resource allocation | ||||
| handling for the new process. Freezer cgroup is required, the rest of the cgroups | ||||
| are optional. The process executor must place its pid inside the correct | ||||
| cgroups before starting the process. This is done so that no child processes or | ||||
| threads can escape the cgroups. | ||||
|  | ||||
| When the process is stopped, the process executor will try (in a best-effort way) | ||||
| to stop all its children and remove the sub-cgroups. | ||||
							
								
								
									
										16
									
								
								vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,16 +0,0 @@ | ||||
| package apparmor | ||||
|  | ||||
| import "errors" | ||||
|  | ||||
| var ( | ||||
| 	// IsEnabled returns true if apparmor is enabled for the host. | ||||
| 	IsEnabled = isEnabled | ||||
|  | ||||
| 	// ApplyProfile will apply the profile with the specified name to the process after | ||||
| 	// the next exec. It is only supported on Linux and produces an ErrApparmorNotEnabled | ||||
| 	// on other platforms. | ||||
| 	ApplyProfile = applyProfile | ||||
|  | ||||
| 	// ErrApparmorNotEnabled indicates that AppArmor is not enabled or not supported. | ||||
| 	ErrApparmorNotEnabled = errors.New("apparmor: config provided but apparmor not supported") | ||||
| ) | ||||
							
								
								
									
										68
									
								
								vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										68
									
								
								vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,68 +0,0 @@ | ||||
| package apparmor | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"sync" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/utils" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	appArmorEnabled bool | ||||
| 	checkAppArmor   sync.Once | ||||
| ) | ||||
|  | ||||
| // isEnabled returns true if apparmor is enabled for the host. | ||||
| func isEnabled() bool { | ||||
| 	checkAppArmor.Do(func() { | ||||
| 		if _, err := os.Stat("/sys/kernel/security/apparmor"); err == nil { | ||||
| 			buf, err := os.ReadFile("/sys/module/apparmor/parameters/enabled") | ||||
| 			appArmorEnabled = err == nil && len(buf) > 1 && buf[0] == 'Y' | ||||
| 		} | ||||
| 	}) | ||||
| 	return appArmorEnabled | ||||
| } | ||||
|  | ||||
| func setProcAttr(attr, value string) error { | ||||
| 	// Under AppArmor you can only change your own attr, so use /proc/self/ | ||||
| 	// instead of /proc/<tid>/ like libapparmor does | ||||
| 	attrPath := "/proc/self/attr/apparmor/" + attr | ||||
| 	if _, err := os.Stat(attrPath); errors.Is(err, os.ErrNotExist) { | ||||
| 		// fall back to the old convention | ||||
| 		attrPath = "/proc/self/attr/" + attr | ||||
| 	} | ||||
|  | ||||
| 	f, err := os.OpenFile(attrPath, os.O_WRONLY, 0) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer f.Close() | ||||
|  | ||||
| 	if err := utils.EnsureProcHandle(f); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	_, err = f.WriteString(value) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // changeOnExec reimplements aa_change_onexec from libapparmor in Go | ||||
| func changeOnExec(name string) error { | ||||
| 	if err := setProcAttr("exec", "exec "+name); err != nil { | ||||
| 		return fmt.Errorf("apparmor failed to apply profile: %w", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // applyProfile will apply the profile with the specified name to the process after | ||||
| // the next exec. It is only supported on Linux and produces an error on other | ||||
| // platforms. | ||||
| func applyProfile(name string) error { | ||||
| 	if name == "" { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return changeOnExec(name) | ||||
| } | ||||
							
								
								
									
										15
									
								
								vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_unsupported.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_unsupported.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,15 +0,0 @@ | ||||
| //go:build !linux | ||||
| // +build !linux | ||||
|  | ||||
| package apparmor | ||||
|  | ||||
| func isEnabled() bool { | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func applyProfile(name string) error { | ||||
| 	if name != "" { | ||||
| 		return ErrApparmorNotEnabled | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										123
									
								
								vendor/github.com/opencontainers/runc/libcontainer/capabilities/capabilities.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										123
									
								
								vendor/github.com/opencontainers/runc/libcontainer/capabilities/capabilities.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,123 +0,0 @@ | ||||
| //go:build linux | ||||
| // +build linux | ||||
|  | ||||
| package capabilities | ||||
|  | ||||
| import ( | ||||
| 	"sort" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/syndtr/gocapability/capability" | ||||
| ) | ||||
|  | ||||
| const allCapabilityTypes = capability.CAPS | capability.BOUNDING | capability.AMBIENT | ||||
|  | ||||
| var ( | ||||
| 	capabilityMap map[string]capability.Cap | ||||
| 	capTypes      = []capability.CapType{ | ||||
| 		capability.BOUNDING, | ||||
| 		capability.PERMITTED, | ||||
| 		capability.INHERITABLE, | ||||
| 		capability.EFFECTIVE, | ||||
| 		capability.AMBIENT, | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	capabilityMap = make(map[string]capability.Cap, capability.CAP_LAST_CAP+1) | ||||
| 	for _, c := range capability.List() { | ||||
| 		if c > capability.CAP_LAST_CAP { | ||||
| 			continue | ||||
| 		} | ||||
| 		capabilityMap["CAP_"+strings.ToUpper(c.String())] = c | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // KnownCapabilities returns the list of the known capabilities. | ||||
| // Used by `runc features`. | ||||
| func KnownCapabilities() []string { | ||||
| 	list := capability.List() | ||||
| 	res := make([]string, len(list)) | ||||
| 	for i, c := range list { | ||||
| 		res[i] = "CAP_" + strings.ToUpper(c.String()) | ||||
| 	} | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| // New creates a new Caps from the given Capabilities config. Unknown Capabilities | ||||
| // or Capabilities that are unavailable in the current environment are ignored, | ||||
| // printing a warning instead. | ||||
| func New(capConfig *configs.Capabilities) (*Caps, error) { | ||||
| 	var ( | ||||
| 		err error | ||||
| 		c   Caps | ||||
| 	) | ||||
|  | ||||
| 	unknownCaps := make(map[string]struct{}) | ||||
| 	c.caps = map[capability.CapType][]capability.Cap{ | ||||
| 		capability.BOUNDING:    capSlice(capConfig.Bounding, unknownCaps), | ||||
| 		capability.EFFECTIVE:   capSlice(capConfig.Effective, unknownCaps), | ||||
| 		capability.INHERITABLE: capSlice(capConfig.Inheritable, unknownCaps), | ||||
| 		capability.PERMITTED:   capSlice(capConfig.Permitted, unknownCaps), | ||||
| 		capability.AMBIENT:     capSlice(capConfig.Ambient, unknownCaps), | ||||
| 	} | ||||
| 	if c.pid, err = capability.NewPid2(0); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if err = c.pid.Load(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if len(unknownCaps) > 0 { | ||||
| 		logrus.Warn("ignoring unknown or unavailable capabilities: ", mapKeys(unknownCaps)) | ||||
| 	} | ||||
| 	return &c, nil | ||||
| } | ||||
|  | ||||
| // capSlice converts the slice of capability names in caps, to their numeric | ||||
| // equivalent, and returns them as a slice. Unknown or unavailable capabilities | ||||
| // are not returned, but appended to unknownCaps. | ||||
| func capSlice(caps []string, unknownCaps map[string]struct{}) []capability.Cap { | ||||
| 	var out []capability.Cap | ||||
| 	for _, c := range caps { | ||||
| 		if v, ok := capabilityMap[c]; !ok { | ||||
| 			unknownCaps[c] = struct{}{} | ||||
| 		} else { | ||||
| 			out = append(out, v) | ||||
| 		} | ||||
| 	} | ||||
| 	return out | ||||
| } | ||||
|  | ||||
| // mapKeys returns the keys of input in sorted order | ||||
| func mapKeys(input map[string]struct{}) []string { | ||||
| 	var keys []string | ||||
| 	for c := range input { | ||||
| 		keys = append(keys, c) | ||||
| 	} | ||||
| 	sort.Strings(keys) | ||||
| 	return keys | ||||
| } | ||||
|  | ||||
| // Caps holds the capabilities for a container. | ||||
| type Caps struct { | ||||
| 	pid  capability.Capabilities | ||||
| 	caps map[capability.CapType][]capability.Cap | ||||
| } | ||||
|  | ||||
| // ApplyBoundingSet sets the capability bounding set to those specified in the whitelist. | ||||
| func (c *Caps) ApplyBoundingSet() error { | ||||
| 	c.pid.Clear(capability.BOUNDING) | ||||
| 	c.pid.Set(capability.BOUNDING, c.caps[capability.BOUNDING]...) | ||||
| 	return c.pid.Apply(capability.BOUNDING) | ||||
| } | ||||
|  | ||||
| // Apply sets all the capabilities for the current process in the config. | ||||
| func (c *Caps) ApplyCaps() error { | ||||
| 	c.pid.Clear(allCapabilityTypes) | ||||
| 	for _, g := range capTypes { | ||||
| 		c.pid.Set(g, c.caps[g]...) | ||||
| 	} | ||||
| 	return c.pid.Apply(allCapabilityTypes) | ||||
| } | ||||
| @@ -1,4 +0,0 @@ | ||||
| //go:build !linux | ||||
| // +build !linux | ||||
|  | ||||
| package capabilities | ||||
							
								
								
									
										86
									
								
								vendor/github.com/opencontainers/runc/libcontainer/configs/validate/rootless.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										86
									
								
								vendor/github.com/opencontainers/runc/libcontainer/configs/validate/rootless.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,86 +0,0 @@ | ||||
| package validate | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs" | ||||
| ) | ||||
|  | ||||
| // rootlessEUID makes sure that the config can be applied when runc | ||||
| // is being executed as a non-root user (euid != 0) in the current user namespace. | ||||
| func (v *ConfigValidator) rootlessEUID(config *configs.Config) error { | ||||
| 	if !config.RootlessEUID { | ||||
| 		return nil | ||||
| 	} | ||||
| 	if err := rootlessEUIDMappings(config); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := rootlessEUIDMount(config); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// XXX: We currently can't verify the user config at all, because | ||||
| 	//      configs.Config doesn't store the user-related configs. So this | ||||
| 	//      has to be verified by setupUser() in init_linux.go. | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func rootlessEUIDMappings(config *configs.Config) error { | ||||
| 	if !config.Namespaces.Contains(configs.NEWUSER) { | ||||
| 		return errors.New("rootless container requires user namespaces") | ||||
| 	} | ||||
| 	// We only require mappings if we are not joining another userns. | ||||
| 	if path := config.Namespaces.PathOf(configs.NEWUSER); path == "" { | ||||
| 		if len(config.UidMappings) == 0 { | ||||
| 			return errors.New("rootless containers requires at least one UID mapping") | ||||
| 		} | ||||
| 		if len(config.GidMappings) == 0 { | ||||
| 			return errors.New("rootless containers requires at least one GID mapping") | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // mount verifies that the user isn't trying to set up any mounts they don't have | ||||
| // the rights to do. In addition, it makes sure that no mount has a `uid=` or | ||||
| // `gid=` option that doesn't resolve to root. | ||||
| func rootlessEUIDMount(config *configs.Config) error { | ||||
| 	// XXX: We could whitelist allowed devices at this point, but I'm not | ||||
| 	//      convinced that's a good idea. The kernel is the best arbiter of | ||||
| 	//      access control. | ||||
|  | ||||
| 	for _, mount := range config.Mounts { | ||||
| 		// Check that the options list doesn't contain any uid= or gid= entries | ||||
| 		// that don't resolve to root. | ||||
| 		for _, opt := range strings.Split(mount.Data, ",") { | ||||
| 			if strings.HasPrefix(opt, "uid=") { | ||||
| 				var uid int | ||||
| 				n, err := fmt.Sscanf(opt, "uid=%d", &uid) | ||||
| 				if n != 1 || err != nil { | ||||
| 					// Ignore unknown mount options. | ||||
| 					continue | ||||
| 				} | ||||
| 				if _, err := config.HostUID(uid); err != nil { | ||||
| 					return fmt.Errorf("cannot specify uid=%d mount option for rootless container: %w", uid, err) | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if strings.HasPrefix(opt, "gid=") { | ||||
| 				var gid int | ||||
| 				n, err := fmt.Sscanf(opt, "gid=%d", &gid) | ||||
| 				if n != 1 || err != nil { | ||||
| 					// Ignore unknown mount options. | ||||
| 					continue | ||||
| 				} | ||||
| 				if _, err := config.HostGID(gid); err != nil { | ||||
| 					return fmt.Errorf("cannot specify gid=%d mount option for rootless container: %w", gid, err) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										306
									
								
								vendor/github.com/opencontainers/runc/libcontainer/configs/validate/validator.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										306
									
								
								vendor/github.com/opencontainers/runc/libcontainer/configs/validate/validator.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,306 +0,0 @@ | ||||
| package validate | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/cgroups" | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs" | ||||
| 	"github.com/opencontainers/runc/libcontainer/intelrdt" | ||||
| 	selinux "github.com/opencontainers/selinux/go-selinux" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| type Validator interface { | ||||
| 	Validate(*configs.Config) error | ||||
| } | ||||
|  | ||||
| func New() Validator { | ||||
| 	return &ConfigValidator{} | ||||
| } | ||||
|  | ||||
| type ConfigValidator struct{} | ||||
|  | ||||
| type check func(config *configs.Config) error | ||||
|  | ||||
| func (v *ConfigValidator) Validate(config *configs.Config) error { | ||||
| 	checks := []check{ | ||||
| 		v.cgroups, | ||||
| 		v.rootfs, | ||||
| 		v.network, | ||||
| 		v.hostname, | ||||
| 		v.security, | ||||
| 		v.usernamespace, | ||||
| 		v.cgroupnamespace, | ||||
| 		v.sysctl, | ||||
| 		v.intelrdt, | ||||
| 		v.rootlessEUID, | ||||
| 	} | ||||
| 	for _, c := range checks { | ||||
| 		if err := c(config); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	// Relaxed validation rules for backward compatibility | ||||
| 	warns := []check{ | ||||
| 		v.mounts, // TODO (runc v1.x.x): make this an error instead of a warning | ||||
| 	} | ||||
| 	for _, c := range warns { | ||||
| 		if err := c(config); err != nil { | ||||
| 			logrus.WithError(err).Warn("invalid configuration") | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // rootfs validates if the rootfs is an absolute path and is not a symlink | ||||
| // to the container's root filesystem. | ||||
| func (v *ConfigValidator) rootfs(config *configs.Config) error { | ||||
| 	if _, err := os.Stat(config.Rootfs); err != nil { | ||||
| 		return fmt.Errorf("invalid rootfs: %w", err) | ||||
| 	} | ||||
| 	cleaned, err := filepath.Abs(config.Rootfs) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("invalid rootfs: %w", err) | ||||
| 	} | ||||
| 	if cleaned, err = filepath.EvalSymlinks(cleaned); err != nil { | ||||
| 		return fmt.Errorf("invalid rootfs: %w", err) | ||||
| 	} | ||||
| 	if filepath.Clean(config.Rootfs) != cleaned { | ||||
| 		return errors.New("invalid rootfs: not an absolute path, or a symlink") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (v *ConfigValidator) network(config *configs.Config) error { | ||||
| 	if !config.Namespaces.Contains(configs.NEWNET) { | ||||
| 		if len(config.Networks) > 0 || len(config.Routes) > 0 { | ||||
| 			return errors.New("unable to apply network settings without a private NET namespace") | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (v *ConfigValidator) hostname(config *configs.Config) error { | ||||
| 	if config.Hostname != "" && !config.Namespaces.Contains(configs.NEWUTS) { | ||||
| 		return errors.New("unable to set hostname without a private UTS namespace") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (v *ConfigValidator) security(config *configs.Config) error { | ||||
| 	// restrict sys without mount namespace | ||||
| 	if (len(config.MaskPaths) > 0 || len(config.ReadonlyPaths) > 0) && | ||||
| 		!config.Namespaces.Contains(configs.NEWNS) { | ||||
| 		return errors.New("unable to restrict sys entries without a private MNT namespace") | ||||
| 	} | ||||
| 	if config.ProcessLabel != "" && !selinux.GetEnabled() { | ||||
| 		return errors.New("selinux label is specified in config, but selinux is disabled or not supported") | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (v *ConfigValidator) usernamespace(config *configs.Config) error { | ||||
| 	if config.Namespaces.Contains(configs.NEWUSER) { | ||||
| 		if _, err := os.Stat("/proc/self/ns/user"); os.IsNotExist(err) { | ||||
| 			return errors.New("user namespaces aren't enabled in the kernel") | ||||
| 		} | ||||
| 		hasPath := config.Namespaces.PathOf(configs.NEWUSER) != "" | ||||
| 		hasMappings := config.UidMappings != nil || config.GidMappings != nil | ||||
| 		if !hasPath && !hasMappings { | ||||
| 			return errors.New("user namespaces enabled, but no namespace path to join nor mappings to apply specified") | ||||
| 		} | ||||
| 		// The hasPath && hasMappings validation case is handled in specconv -- | ||||
| 		// we cache the mappings in Config during specconv in the hasPath case, | ||||
| 		// so we cannot do that validation here. | ||||
| 	} else { | ||||
| 		if config.UidMappings != nil || config.GidMappings != nil { | ||||
| 			return errors.New("user namespace mappings specified, but user namespace isn't enabled in the config") | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (v *ConfigValidator) cgroupnamespace(config *configs.Config) error { | ||||
| 	if config.Namespaces.Contains(configs.NEWCGROUP) { | ||||
| 		if _, err := os.Stat("/proc/self/ns/cgroup"); os.IsNotExist(err) { | ||||
| 			return errors.New("cgroup namespaces aren't enabled in the kernel") | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // convertSysctlVariableToDotsSeparator can return sysctl variables in dots separator format. | ||||
| // The '/' separator is also accepted in place of a '.'. | ||||
| // Convert the sysctl variables to dots separator format for validation. | ||||
| // More info: sysctl(8), sysctl.d(5). | ||||
| // | ||||
| // For example: | ||||
| // Input sysctl variable "net/ipv4/conf/eno2.100.rp_filter" | ||||
| // will return the converted value "net.ipv4.conf.eno2/100.rp_filter" | ||||
| func convertSysctlVariableToDotsSeparator(val string) string { | ||||
| 	if val == "" { | ||||
| 		return val | ||||
| 	} | ||||
| 	firstSepIndex := strings.IndexAny(val, "./") | ||||
| 	if firstSepIndex == -1 || val[firstSepIndex] == '.' { | ||||
| 		return val | ||||
| 	} | ||||
|  | ||||
| 	f := func(r rune) rune { | ||||
| 		switch r { | ||||
| 		case '.': | ||||
| 			return '/' | ||||
| 		case '/': | ||||
| 			return '.' | ||||
| 		} | ||||
| 		return r | ||||
| 	} | ||||
| 	return strings.Map(f, val) | ||||
| } | ||||
|  | ||||
| // sysctl validates that the specified sysctl keys are valid or not. | ||||
| // /proc/sys isn't completely namespaced and depending on which namespaces | ||||
| // are specified, a subset of sysctls are permitted. | ||||
| func (v *ConfigValidator) sysctl(config *configs.Config) error { | ||||
| 	validSysctlMap := map[string]bool{ | ||||
| 		"kernel.msgmax":          true, | ||||
| 		"kernel.msgmnb":          true, | ||||
| 		"kernel.msgmni":          true, | ||||
| 		"kernel.sem":             true, | ||||
| 		"kernel.shmall":          true, | ||||
| 		"kernel.shmmax":          true, | ||||
| 		"kernel.shmmni":          true, | ||||
| 		"kernel.shm_rmid_forced": true, | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		netOnce    sync.Once | ||||
| 		hostnet    bool | ||||
| 		hostnetErr error | ||||
| 	) | ||||
|  | ||||
| 	for s := range config.Sysctl { | ||||
| 		s := convertSysctlVariableToDotsSeparator(s) | ||||
| 		if validSysctlMap[s] || strings.HasPrefix(s, "fs.mqueue.") { | ||||
| 			if config.Namespaces.Contains(configs.NEWIPC) { | ||||
| 				continue | ||||
| 			} else { | ||||
| 				return fmt.Errorf("sysctl %q is not allowed in the hosts ipc namespace", s) | ||||
| 			} | ||||
| 		} | ||||
| 		if strings.HasPrefix(s, "net.") { | ||||
| 			// Is container using host netns? | ||||
| 			// Here "host" means "current", not "initial". | ||||
| 			netOnce.Do(func() { | ||||
| 				if !config.Namespaces.Contains(configs.NEWNET) { | ||||
| 					hostnet = true | ||||
| 					return | ||||
| 				} | ||||
| 				path := config.Namespaces.PathOf(configs.NEWNET) | ||||
| 				if path == "" { | ||||
| 					// own netns, so hostnet = false | ||||
| 					return | ||||
| 				} | ||||
| 				hostnet, hostnetErr = isHostNetNS(path) | ||||
| 			}) | ||||
| 			if hostnetErr != nil { | ||||
| 				return fmt.Errorf("invalid netns path: %w", hostnetErr) | ||||
| 			} | ||||
| 			if hostnet { | ||||
| 				return fmt.Errorf("sysctl %q not allowed in host network namespace", s) | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
| 		if config.Namespaces.Contains(configs.NEWUTS) { | ||||
| 			switch s { | ||||
| 			case "kernel.domainname": | ||||
| 				// This is namespaced and there's no explicit OCI field for it. | ||||
| 				continue | ||||
| 			case "kernel.hostname": | ||||
| 				// This is namespaced but there's a conflicting (dedicated) OCI field for it. | ||||
| 				return fmt.Errorf("sysctl %q is not allowed as it conflicts with the OCI %q field", s, "hostname") | ||||
| 			} | ||||
| 		} | ||||
| 		return fmt.Errorf("sysctl %q is not in a separate kernel namespace", s) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (v *ConfigValidator) intelrdt(config *configs.Config) error { | ||||
| 	if config.IntelRdt != nil { | ||||
| 		if config.IntelRdt.ClosID == "." || config.IntelRdt.ClosID == ".." || strings.Contains(config.IntelRdt.ClosID, "/") { | ||||
| 			return fmt.Errorf("invalid intelRdt.ClosID %q", config.IntelRdt.ClosID) | ||||
| 		} | ||||
|  | ||||
| 		if !intelrdt.IsCATEnabled() && config.IntelRdt.L3CacheSchema != "" { | ||||
| 			return errors.New("intelRdt.l3CacheSchema is specified in config, but Intel RDT/CAT is not enabled") | ||||
| 		} | ||||
| 		if !intelrdt.IsMBAEnabled() && config.IntelRdt.MemBwSchema != "" { | ||||
| 			return errors.New("intelRdt.memBwSchema is specified in config, but Intel RDT/MBA is not enabled") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (v *ConfigValidator) cgroups(config *configs.Config) error { | ||||
| 	c := config.Cgroups | ||||
| 	if c == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	if (c.Name != "" || c.Parent != "") && c.Path != "" { | ||||
| 		return fmt.Errorf("cgroup: either Path or Name and Parent should be used, got %+v", c) | ||||
| 	} | ||||
|  | ||||
| 	r := c.Resources | ||||
| 	if r == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	if !cgroups.IsCgroup2UnifiedMode() && r.Unified != nil { | ||||
| 		return cgroups.ErrV1NoUnified | ||||
| 	} | ||||
|  | ||||
| 	if cgroups.IsCgroup2UnifiedMode() { | ||||
| 		_, err := cgroups.ConvertMemorySwapToCgroupV2Value(r.MemorySwap, r.Memory) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (v *ConfigValidator) mounts(config *configs.Config) error { | ||||
| 	for _, m := range config.Mounts { | ||||
| 		if !filepath.IsAbs(m.Destination) { | ||||
| 			return fmt.Errorf("invalid mount %+v: mount destination not absolute", m) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func isHostNetNS(path string) (bool, error) { | ||||
| 	const currentProcessNetns = "/proc/self/ns/net" | ||||
|  | ||||
| 	var st1, st2 unix.Stat_t | ||||
|  | ||||
| 	if err := unix.Stat(currentProcessNetns, &st1); err != nil { | ||||
| 		return false, &os.PathError{Op: "stat", Path: currentProcessNetns, Err: err} | ||||
| 	} | ||||
| 	if err := unix.Stat(path, &st2); err != nil { | ||||
| 		return false, &os.PathError{Op: "stat", Path: path, Err: err} | ||||
| 	} | ||||
|  | ||||
| 	return (st1.Dev == st2.Dev) && (st1.Ino == st2.Ino), nil | ||||
| } | ||||
							
								
								
									
										41
									
								
								vendor/github.com/opencontainers/runc/libcontainer/console_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										41
									
								
								vendor/github.com/opencontainers/runc/libcontainer/console_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,41 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| // mount initializes the console inside the rootfs mounting with the specified mount label | ||||
| // and applying the correct ownership of the console. | ||||
| func mountConsole(slavePath string) error { | ||||
| 	oldMask := unix.Umask(0o000) | ||||
| 	defer unix.Umask(oldMask) | ||||
| 	f, err := os.Create("/dev/console") | ||||
| 	if err != nil && !os.IsExist(err) { | ||||
| 		return err | ||||
| 	} | ||||
| 	if f != nil { | ||||
| 		f.Close() | ||||
| 	} | ||||
| 	return mount(slavePath, "/dev/console", "", "bind", unix.MS_BIND, "") | ||||
| } | ||||
|  | ||||
| // dupStdio opens the slavePath for the console and dups the fds to the current | ||||
| // processes stdio, fd 0,1,2. | ||||
| func dupStdio(slavePath string) error { | ||||
| 	fd, err := unix.Open(slavePath, unix.O_RDWR, 0) | ||||
| 	if err != nil { | ||||
| 		return &os.PathError{ | ||||
| 			Op:   "open", | ||||
| 			Path: slavePath, | ||||
| 			Err:  err, | ||||
| 		} | ||||
| 	} | ||||
| 	for _, i := range []int{0, 1, 2} { | ||||
| 		if err := unix.Dup3(fd, i, 0); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										130
									
								
								vendor/github.com/opencontainers/runc/libcontainer/container.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										130
									
								
								vendor/github.com/opencontainers/runc/libcontainer/container.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,130 +0,0 @@ | ||||
| // Package libcontainer provides a native Go implementation for creating containers | ||||
| // with namespaces, cgroups, capabilities, and filesystem access controls. | ||||
| // It allows you to manage the lifecycle of the container performing additional operations | ||||
| // after the container is created. | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs" | ||||
| 	"github.com/opencontainers/runtime-spec/specs-go" | ||||
| ) | ||||
|  | ||||
| // Status is the status of a container. | ||||
| type Status int | ||||
|  | ||||
| const ( | ||||
| 	// Created is the status that denotes the container exists but has not been run yet. | ||||
| 	Created Status = iota | ||||
| 	// Running is the status that denotes the container exists and is running. | ||||
| 	Running | ||||
| 	// Pausing is the status that denotes the container exists, it is in the process of being paused. | ||||
| 	Pausing | ||||
| 	// Paused is the status that denotes the container exists, but all its processes are paused. | ||||
| 	Paused | ||||
| 	// Stopped is the status that denotes the container does not have a created or running process. | ||||
| 	Stopped | ||||
| ) | ||||
|  | ||||
| func (s Status) String() string { | ||||
| 	switch s { | ||||
| 	case Created: | ||||
| 		return "created" | ||||
| 	case Running: | ||||
| 		return "running" | ||||
| 	case Pausing: | ||||
| 		return "pausing" | ||||
| 	case Paused: | ||||
| 		return "paused" | ||||
| 	case Stopped: | ||||
| 		return "stopped" | ||||
| 	default: | ||||
| 		return "unknown" | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // BaseState represents the platform agnostic pieces relating to a | ||||
| // running container's state | ||||
| type BaseState struct { | ||||
| 	// ID is the container ID. | ||||
| 	ID string `json:"id"` | ||||
|  | ||||
| 	// InitProcessPid is the init process id in the parent namespace. | ||||
| 	InitProcessPid int `json:"init_process_pid"` | ||||
|  | ||||
| 	// InitProcessStartTime is the init process start time in clock cycles since boot time. | ||||
| 	InitProcessStartTime uint64 `json:"init_process_start"` | ||||
|  | ||||
| 	// Created is the unix timestamp for the creation time of the container in UTC | ||||
| 	Created time.Time `json:"created"` | ||||
|  | ||||
| 	// Config is the container's configuration. | ||||
| 	Config configs.Config `json:"config"` | ||||
| } | ||||
|  | ||||
| // BaseContainer is a libcontainer container object. | ||||
| // | ||||
| // Each container is thread-safe within the same process. Since a container can | ||||
| // be destroyed by a separate process, any function may return that the container | ||||
| // was not found. BaseContainer includes methods that are platform agnostic. | ||||
| type BaseContainer interface { | ||||
| 	// Returns the ID of the container | ||||
| 	ID() string | ||||
|  | ||||
| 	// Returns the current status of the container. | ||||
| 	Status() (Status, error) | ||||
|  | ||||
| 	// State returns the current container's state information. | ||||
| 	State() (*State, error) | ||||
|  | ||||
| 	// OCIState returns the current container's state information. | ||||
| 	OCIState() (*specs.State, error) | ||||
|  | ||||
| 	// Returns the current config of the container. | ||||
| 	Config() configs.Config | ||||
|  | ||||
| 	// Returns the PIDs inside this container. The PIDs are in the namespace of the calling process. | ||||
| 	// | ||||
| 	// Some of the returned PIDs may no longer refer to processes in the Container, unless | ||||
| 	// the Container state is PAUSED in which case every PID in the slice is valid. | ||||
| 	Processes() ([]int, error) | ||||
|  | ||||
| 	// Returns statistics for the container. | ||||
| 	Stats() (*Stats, error) | ||||
|  | ||||
| 	// Set resources of container as configured | ||||
| 	// | ||||
| 	// We can use this to change resources when containers are running. | ||||
| 	// | ||||
| 	Set(config configs.Config) error | ||||
|  | ||||
| 	// Start a process inside the container. Returns error if process fails to | ||||
| 	// start. You can track process lifecycle with passed Process structure. | ||||
| 	Start(process *Process) (err error) | ||||
|  | ||||
| 	// Run immediately starts the process inside the container.  Returns error if process | ||||
| 	// fails to start.  It does not block waiting for the exec fifo  after start returns but | ||||
| 	// opens the fifo after start returns. | ||||
| 	Run(process *Process) (err error) | ||||
|  | ||||
| 	// Destroys the container, if its in a valid state, after killing any | ||||
| 	// remaining running processes. | ||||
| 	// | ||||
| 	// Any event registrations are removed before the container is destroyed. | ||||
| 	// No error is returned if the container is already destroyed. | ||||
| 	// | ||||
| 	// Running containers must first be stopped using Signal(..). | ||||
| 	// Paused containers must first be resumed using Resume(..). | ||||
| 	Destroy() error | ||||
|  | ||||
| 	// Signal sends the provided signal code to the container's initial process. | ||||
| 	// | ||||
| 	// If all is specified the signal is sent to all processes in the container | ||||
| 	// including the initial process. | ||||
| 	Signal(s os.Signal, all bool) error | ||||
|  | ||||
| 	// Exec signals the container to exec the users process at the end of the init. | ||||
| 	Exec() error | ||||
| } | ||||
							
								
								
									
										2267
									
								
								vendor/github.com/opencontainers/runc/libcontainer/container_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2267
									
								
								vendor/github.com/opencontainers/runc/libcontainer/container_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										34
									
								
								vendor/github.com/opencontainers/runc/libcontainer/criu_opts_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								vendor/github.com/opencontainers/runc/libcontainer/criu_opts_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,34 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import criu "github.com/checkpoint-restore/go-criu/v5/rpc" | ||||
|  | ||||
| type CriuPageServerInfo struct { | ||||
| 	Address string // IP address of CRIU page server | ||||
| 	Port    int32  // port number of CRIU page server | ||||
| } | ||||
|  | ||||
| type VethPairName struct { | ||||
| 	ContainerInterfaceName string | ||||
| 	HostInterfaceName      string | ||||
| } | ||||
|  | ||||
| type CriuOpts struct { | ||||
| 	ImagesDirectory         string             // directory for storing image files | ||||
| 	WorkDirectory           string             // directory to cd and write logs/pidfiles/stats to | ||||
| 	ParentImage             string             // directory for storing parent image files in pre-dump and dump | ||||
| 	LeaveRunning            bool               // leave container in running state after checkpoint | ||||
| 	TcpEstablished          bool               // checkpoint/restore established TCP connections | ||||
| 	ExternalUnixConnections bool               // allow external unix connections | ||||
| 	ShellJob                bool               // allow to dump and restore shell jobs | ||||
| 	FileLocks               bool               // handle file locks, for safety | ||||
| 	PreDump                 bool               // call criu predump to perform iterative checkpoint | ||||
| 	PageServer              CriuPageServerInfo // allow to dump to criu page server | ||||
| 	VethPairs               []VethPairName     // pass the veth to criu when restore | ||||
| 	ManageCgroupsMode       criu.CriuCgMode    // dump or restore cgroup mode | ||||
| 	EmptyNs                 uint32             // don't c/r properties for namespace from this mask | ||||
| 	AutoDedup               bool               // auto deduplication for incremental dumps | ||||
| 	LazyPages               bool               // restore memory pages lazily using userfaultfd | ||||
| 	StatusFd                int                // fd for feedback when lazy server is ready | ||||
| 	LsmProfile              string             // LSM profile used to restore the container | ||||
| 	LsmMountContext         string             // LSM mount context value to use during restore | ||||
| } | ||||
							
								
								
									
										17
									
								
								vendor/github.com/opencontainers/runc/libcontainer/eaccess_go119.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/opencontainers/runc/libcontainer/eaccess_go119.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,17 +0,0 @@ | ||||
| //go:build !go1.20 | ||||
| // +build !go1.20 | ||||
|  | ||||
| package libcontainer | ||||
|  | ||||
| import "golang.org/x/sys/unix" | ||||
|  | ||||
| func eaccess(path string) error { | ||||
| 	// This check is similar to access(2) with X_OK except for | ||||
| 	// setuid/setgid binaries where it checks against the effective | ||||
| 	// (rather than real) uid and gid. It is not needed in go 1.20 | ||||
| 	// and beyond and will be removed later. | ||||
|  | ||||
| 	// Relies on code added in https://go-review.googlesource.com/c/sys/+/468877 | ||||
| 	// and older CLs linked from there. | ||||
| 	return unix.Faccessat(unix.AT_FDCWD, path, unix.X_OK, unix.AT_EACCESS) | ||||
| } | ||||
							
								
								
									
										10
									
								
								vendor/github.com/opencontainers/runc/libcontainer/eaccess_stub.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/opencontainers/runc/libcontainer/eaccess_stub.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,10 +0,0 @@ | ||||
| //go:build go1.20 | ||||
|  | ||||
| package libcontainer | ||||
|  | ||||
| func eaccess(path string) error { | ||||
| 	// Not needed in Go 1.20+ as the functionality is already in there | ||||
| 	// (added by https://go.dev/cl/416115, https://go.dev/cl/414824, | ||||
| 	// and fixed in Go 1.20.2 by https://go.dev/cl/469956). | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										13
									
								
								vendor/github.com/opencontainers/runc/libcontainer/error.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/opencontainers/runc/libcontainer/error.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,13 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import "errors" | ||||
|  | ||||
| var ( | ||||
| 	ErrExist      = errors.New("container with given ID already exists") | ||||
| 	ErrInvalidID  = errors.New("invalid container ID format") | ||||
| 	ErrNotExist   = errors.New("container does not exist") | ||||
| 	ErrPaused     = errors.New("container paused") | ||||
| 	ErrRunning    = errors.New("container still running") | ||||
| 	ErrNotRunning = errors.New("container not running") | ||||
| 	ErrNotPaused  = errors.New("container not paused") | ||||
| ) | ||||
							
								
								
									
										30
									
								
								vendor/github.com/opencontainers/runc/libcontainer/factory.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/opencontainers/runc/libcontainer/factory.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,30 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs" | ||||
| ) | ||||
|  | ||||
| type Factory interface { | ||||
| 	// Creates a new container with the given id and starts the initial process inside it. | ||||
| 	// id must be a string containing only letters, digits and underscores and must contain | ||||
| 	// between 1 and 1024 characters, inclusive. | ||||
| 	// | ||||
| 	// The id must not already be in use by an existing container. Containers created using | ||||
| 	// a factory with the same path (and filesystem) must have distinct ids. | ||||
| 	// | ||||
| 	// Returns the new container with a running process. | ||||
| 	// | ||||
| 	// On error, any partially created container parts are cleaned up (the operation is atomic). | ||||
| 	Create(id string, config *configs.Config) (Container, error) | ||||
|  | ||||
| 	// Load takes an ID for an existing container and returns the container information | ||||
| 	// from the state.  This presents a read only view of the container. | ||||
| 	Load(id string) (Container, error) | ||||
|  | ||||
| 	// StartInitialization is an internal API to libcontainer used during the reexec of the | ||||
| 	// container. | ||||
| 	StartInitialization() error | ||||
|  | ||||
| 	// Type returns info string about factory type (e.g. lxc, libcontainer...) | ||||
| 	Type() string | ||||
| } | ||||
							
								
								
									
										402
									
								
								vendor/github.com/opencontainers/runc/libcontainer/factory_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										402
									
								
								vendor/github.com/opencontainers/runc/libcontainer/factory_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,402 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"regexp" | ||||
| 	"runtime/debug" | ||||
| 	"strconv" | ||||
|  | ||||
| 	securejoin "github.com/cyphar/filepath-securejoin" | ||||
| 	"github.com/moby/sys/mountinfo" | ||||
| 	"golang.org/x/sys/unix" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/cgroups/manager" | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs" | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs/validate" | ||||
| 	"github.com/opencontainers/runc/libcontainer/intelrdt" | ||||
| 	"github.com/opencontainers/runc/libcontainer/utils" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	stateFilename    = "state.json" | ||||
| 	execFifoFilename = "exec.fifo" | ||||
| ) | ||||
|  | ||||
| var idRegex = regexp.MustCompile(`^[\w+-\.]+$`) | ||||
|  | ||||
| // InitArgs returns an options func to configure a LinuxFactory with the | ||||
| // provided init binary path and arguments. | ||||
| func InitArgs(args ...string) func(*LinuxFactory) error { | ||||
| 	return func(l *LinuxFactory) (err error) { | ||||
| 		if len(args) > 0 { | ||||
| 			// Resolve relative paths to ensure that its available | ||||
| 			// after directory changes. | ||||
| 			if args[0], err = filepath.Abs(args[0]); err != nil { | ||||
| 				// The only error returned from filepath.Abs is | ||||
| 				// the one from os.Getwd, i.e. a system error. | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		l.InitArgs = args | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // TmpfsRoot is an option func to mount LinuxFactory.Root to tmpfs. | ||||
| func TmpfsRoot(l *LinuxFactory) error { | ||||
| 	mounted, err := mountinfo.Mounted(l.Root) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if !mounted { | ||||
| 		if err := mount("tmpfs", l.Root, "", "tmpfs", 0, ""); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // CriuPath returns an option func to configure a LinuxFactory with the | ||||
| // provided criupath | ||||
| func CriuPath(criupath string) func(*LinuxFactory) error { | ||||
| 	return func(l *LinuxFactory) error { | ||||
| 		l.CriuPath = criupath | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // New returns a linux based container factory based in the root directory and | ||||
| // configures the factory with the provided option funcs. | ||||
| func New(root string, options ...func(*LinuxFactory) error) (Factory, error) { | ||||
| 	if root != "" { | ||||
| 		if err := os.MkdirAll(root, 0o700); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	l := &LinuxFactory{ | ||||
| 		Root:      root, | ||||
| 		InitPath:  "/proc/self/exe", | ||||
| 		InitArgs:  []string{os.Args[0], "init"}, | ||||
| 		Validator: validate.New(), | ||||
| 		CriuPath:  "criu", | ||||
| 	} | ||||
|  | ||||
| 	for _, opt := range options { | ||||
| 		if opt == nil { | ||||
| 			continue | ||||
| 		} | ||||
| 		if err := opt(l); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	return l, nil | ||||
| } | ||||
|  | ||||
| // LinuxFactory implements the default factory interface for linux based systems. | ||||
| type LinuxFactory struct { | ||||
| 	// Root directory for the factory to store state. | ||||
| 	Root string | ||||
|  | ||||
| 	// InitPath is the path for calling the init responsibilities for spawning | ||||
| 	// a container. | ||||
| 	InitPath string | ||||
|  | ||||
| 	// InitArgs are arguments for calling the init responsibilities for spawning | ||||
| 	// a container. | ||||
| 	InitArgs []string | ||||
|  | ||||
| 	// CriuPath is the path to the criu binary used for checkpoint and restore of | ||||
| 	// containers. | ||||
| 	CriuPath string | ||||
|  | ||||
| 	// New{u,g}idmapPath is the path to the binaries used for mapping with | ||||
| 	// rootless containers. | ||||
| 	NewuidmapPath string | ||||
| 	NewgidmapPath string | ||||
|  | ||||
| 	// Validator provides validation to container configurations. | ||||
| 	Validator validate.Validator | ||||
| } | ||||
|  | ||||
| func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, error) { | ||||
| 	if l.Root == "" { | ||||
| 		return nil, errors.New("root not set") | ||||
| 	} | ||||
| 	if err := l.validateID(id); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if err := l.Validator.Validate(config); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	containerRoot, err := securejoin.SecureJoin(l.Root, id) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if _, err := os.Stat(containerRoot); err == nil { | ||||
| 		return nil, ErrExist | ||||
| 	} else if !os.IsNotExist(err) { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	cm, err := manager.New(config.Cgroups) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// Check that cgroup does not exist or empty (no processes). | ||||
| 	// Note for cgroup v1 this check is not thorough, as there are multiple | ||||
| 	// separate hierarchies, while both Exists() and GetAllPids() only use | ||||
| 	// one for "devices" controller (assuming others are the same, which is | ||||
| 	// probably true in almost all scenarios). Checking all the hierarchies | ||||
| 	// would be too expensive. | ||||
| 	if cm.Exists() { | ||||
| 		pids, err := cm.GetAllPids() | ||||
| 		// Reading PIDs can race with cgroups removal, so ignore ENOENT and ENODEV. | ||||
| 		if err != nil && !errors.Is(err, os.ErrNotExist) && !errors.Is(err, unix.ENODEV) { | ||||
| 			return nil, fmt.Errorf("unable to get cgroup PIDs: %w", err) | ||||
| 		} | ||||
| 		if len(pids) != 0 { | ||||
| 			if config.Cgroups.Systemd { | ||||
| 				// systemd cgroup driver can't add a pid to an | ||||
| 				// existing systemd unit and will return an | ||||
| 				// error anyway, so let's error out early. | ||||
| 				return nil, fmt.Errorf("container's cgroup is not empty: %d process(es) found", len(pids)) | ||||
| 			} | ||||
| 			// TODO: return an error. | ||||
| 			logrus.Warnf("container's cgroup is not empty: %d process(es) found", len(pids)) | ||||
| 			logrus.Warn("DEPRECATED: running container in a non-empty cgroup won't be supported in runc 1.2; https://github.com/opencontainers/runc/issues/3132") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Check that cgroup is not frozen. Do not use Exists() here | ||||
| 	// since in cgroup v1 it only checks "devices" controller. | ||||
| 	st, err := cm.GetFreezerState() | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("unable to get cgroup freezer state: %w", err) | ||||
| 	} | ||||
| 	if st == configs.Frozen { | ||||
| 		return nil, errors.New("container's cgroup unexpectedly frozen") | ||||
| 	} | ||||
|  | ||||
| 	if err := os.MkdirAll(containerRoot, 0o711); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if err := os.Chown(containerRoot, unix.Geteuid(), unix.Getegid()); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	c := &linuxContainer{ | ||||
| 		id:              id, | ||||
| 		root:            containerRoot, | ||||
| 		config:          config, | ||||
| 		initPath:        l.InitPath, | ||||
| 		initArgs:        l.InitArgs, | ||||
| 		criuPath:        l.CriuPath, | ||||
| 		newuidmapPath:   l.NewuidmapPath, | ||||
| 		newgidmapPath:   l.NewgidmapPath, | ||||
| 		cgroupManager:   cm, | ||||
| 		intelRdtManager: intelrdt.NewManager(config, id, ""), | ||||
| 	} | ||||
| 	c.state = &stoppedState{c: c} | ||||
| 	return c, nil | ||||
| } | ||||
|  | ||||
| func (l *LinuxFactory) Load(id string) (Container, error) { | ||||
| 	if l.Root == "" { | ||||
| 		return nil, errors.New("root not set") | ||||
| 	} | ||||
| 	// when load, we need to check id is valid or not. | ||||
| 	if err := l.validateID(id); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	containerRoot, err := securejoin.SecureJoin(l.Root, id) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	state, err := l.loadState(containerRoot) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	r := &nonChildProcess{ | ||||
| 		processPid:       state.InitProcessPid, | ||||
| 		processStartTime: state.InitProcessStartTime, | ||||
| 		fds:              state.ExternalDescriptors, | ||||
| 	} | ||||
| 	cm, err := manager.NewWithPaths(state.Config.Cgroups, state.CgroupPaths) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	c := &linuxContainer{ | ||||
| 		initProcess:          r, | ||||
| 		initProcessStartTime: state.InitProcessStartTime, | ||||
| 		id:                   id, | ||||
| 		config:               &state.Config, | ||||
| 		initPath:             l.InitPath, | ||||
| 		initArgs:             l.InitArgs, | ||||
| 		criuPath:             l.CriuPath, | ||||
| 		newuidmapPath:        l.NewuidmapPath, | ||||
| 		newgidmapPath:        l.NewgidmapPath, | ||||
| 		cgroupManager:        cm, | ||||
| 		intelRdtManager:      intelrdt.NewManager(&state.Config, id, state.IntelRdtPath), | ||||
| 		root:                 containerRoot, | ||||
| 		created:              state.Created, | ||||
| 	} | ||||
| 	c.state = &loadedState{c: c} | ||||
| 	if err := c.refreshState(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return c, nil | ||||
| } | ||||
|  | ||||
| func (l *LinuxFactory) Type() string { | ||||
| 	return "libcontainer" | ||||
| } | ||||
|  | ||||
| // StartInitialization loads a container by opening the pipe fd from the parent to read the configuration and state | ||||
| // This is a low level implementation detail of the reexec and should not be consumed externally | ||||
| func (l *LinuxFactory) StartInitialization() (err error) { | ||||
| 	// Get the INITPIPE. | ||||
| 	envInitPipe := os.Getenv("_LIBCONTAINER_INITPIPE") | ||||
| 	pipefd, err := strconv.Atoi(envInitPipe) | ||||
| 	if err != nil { | ||||
| 		err = fmt.Errorf("unable to convert _LIBCONTAINER_INITPIPE: %w", err) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
| 	pipe := os.NewFile(uintptr(pipefd), "pipe") | ||||
| 	defer pipe.Close() | ||||
|  | ||||
| 	defer func() { | ||||
| 		// We have an error during the initialization of the container's init, | ||||
| 		// send it back to the parent process in the form of an initError. | ||||
| 		if werr := writeSync(pipe, procError); werr != nil { | ||||
| 			fmt.Fprintln(os.Stderr, err) | ||||
| 			return | ||||
| 		} | ||||
| 		if werr := utils.WriteJSON(pipe, &initError{Message: err.Error()}); werr != nil { | ||||
| 			fmt.Fprintln(os.Stderr, err) | ||||
| 			return | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	// Only init processes have FIFOFD. | ||||
| 	fifofd := -1 | ||||
| 	envInitType := os.Getenv("_LIBCONTAINER_INITTYPE") | ||||
| 	it := initType(envInitType) | ||||
| 	if it == initStandard { | ||||
| 		envFifoFd := os.Getenv("_LIBCONTAINER_FIFOFD") | ||||
| 		if fifofd, err = strconv.Atoi(envFifoFd); err != nil { | ||||
| 			return fmt.Errorf("unable to convert _LIBCONTAINER_FIFOFD: %w", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var consoleSocket *os.File | ||||
| 	if envConsole := os.Getenv("_LIBCONTAINER_CONSOLE"); envConsole != "" { | ||||
| 		console, err := strconv.Atoi(envConsole) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("unable to convert _LIBCONTAINER_CONSOLE: %w", err) | ||||
| 		} | ||||
| 		consoleSocket = os.NewFile(uintptr(console), "console-socket") | ||||
| 		defer consoleSocket.Close() | ||||
| 	} | ||||
|  | ||||
| 	logPipeFdStr := os.Getenv("_LIBCONTAINER_LOGPIPE") | ||||
| 	logPipeFd, err := strconv.Atoi(logPipeFdStr) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("unable to convert _LIBCONTAINER_LOGPIPE: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// Get mount files (O_PATH). | ||||
| 	mountFds, err := parseMountFds() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// clear the current process's environment to clean any libcontainer | ||||
| 	// specific env vars. | ||||
| 	os.Clearenv() | ||||
|  | ||||
| 	defer func() { | ||||
| 		if e := recover(); e != nil { | ||||
| 			if ee, ok := e.(error); ok { | ||||
| 				err = fmt.Errorf("panic from initialization: %w, %s", ee, debug.Stack()) | ||||
| 			} else { | ||||
| 				err = fmt.Errorf("panic from initialization: %v, %s", e, debug.Stack()) | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	i, err := newContainerInit(it, pipe, consoleSocket, fifofd, logPipeFd, mountFds) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// If Init succeeds, syscall.Exec will not return, hence none of the defers will be called. | ||||
| 	return i.Init() | ||||
| } | ||||
|  | ||||
| func (l *LinuxFactory) loadState(root string) (*State, error) { | ||||
| 	stateFilePath, err := securejoin.SecureJoin(root, stateFilename) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	f, err := os.Open(stateFilePath) | ||||
| 	if err != nil { | ||||
| 		if os.IsNotExist(err) { | ||||
| 			return nil, ErrNotExist | ||||
| 		} | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer f.Close() | ||||
| 	var state *State | ||||
| 	if err := json.NewDecoder(f).Decode(&state); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return state, nil | ||||
| } | ||||
|  | ||||
| func (l *LinuxFactory) validateID(id string) error { | ||||
| 	if !idRegex.MatchString(id) || string(os.PathSeparator)+id != utils.CleanPath(string(os.PathSeparator)+id) { | ||||
| 		return ErrInvalidID | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // NewuidmapPath returns an option func to configure a LinuxFactory with the | ||||
| // provided .. | ||||
| func NewuidmapPath(newuidmapPath string) func(*LinuxFactory) error { | ||||
| 	return func(l *LinuxFactory) error { | ||||
| 		l.NewuidmapPath = newuidmapPath | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // NewgidmapPath returns an option func to configure a LinuxFactory with the | ||||
| // provided .. | ||||
| func NewgidmapPath(newgidmapPath string) func(*LinuxFactory) error { | ||||
| 	return func(l *LinuxFactory) error { | ||||
| 		l.NewgidmapPath = newgidmapPath | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func parseMountFds() ([]int, error) { | ||||
| 	fdsJson := os.Getenv("_LIBCONTAINER_MOUNT_FDS") | ||||
| 	if fdsJson == "" { | ||||
| 		// Always return the nil slice if no fd is present. | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	var mountFds []int | ||||
| 	if err := json.Unmarshal([]byte(fdsJson), &mountFds); err != nil { | ||||
| 		return nil, fmt.Errorf("Error unmarshalling _LIBCONTAINER_MOUNT_FDS: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return mountFds, nil | ||||
| } | ||||
							
								
								
									
										641
									
								
								vendor/github.com/opencontainers/runc/libcontainer/init_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										641
									
								
								vendor/github.com/opencontainers/runc/libcontainer/init_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,641 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/containerd/console" | ||||
| 	"github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/vishvananda/netlink" | ||||
| 	"golang.org/x/sys/unix" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/capabilities" | ||||
| 	"github.com/opencontainers/runc/libcontainer/cgroups" | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs" | ||||
| 	"github.com/opencontainers/runc/libcontainer/system" | ||||
| 	"github.com/opencontainers/runc/libcontainer/user" | ||||
| 	"github.com/opencontainers/runc/libcontainer/utils" | ||||
| ) | ||||
|  | ||||
| type initType string | ||||
|  | ||||
| const ( | ||||
| 	initSetns    initType = "setns" | ||||
| 	initStandard initType = "standard" | ||||
| ) | ||||
|  | ||||
| type pid struct { | ||||
| 	Pid           int `json:"stage2_pid"` | ||||
| 	PidFirstChild int `json:"stage1_pid"` | ||||
| } | ||||
|  | ||||
| // network is an internal struct used to setup container networks. | ||||
| type network struct { | ||||
| 	configs.Network | ||||
|  | ||||
| 	// TempVethPeerName is a unique temporary veth peer name that was placed into | ||||
| 	// the container's namespace. | ||||
| 	TempVethPeerName string `json:"temp_veth_peer_name"` | ||||
| } | ||||
|  | ||||
| // initConfig is used for transferring parameters from Exec() to Init() | ||||
| type initConfig struct { | ||||
| 	Args             []string              `json:"args"` | ||||
| 	Env              []string              `json:"env"` | ||||
| 	Cwd              string                `json:"cwd"` | ||||
| 	Capabilities     *configs.Capabilities `json:"capabilities"` | ||||
| 	ProcessLabel     string                `json:"process_label"` | ||||
| 	AppArmorProfile  string                `json:"apparmor_profile"` | ||||
| 	NoNewPrivileges  bool                  `json:"no_new_privileges"` | ||||
| 	User             string                `json:"user"` | ||||
| 	AdditionalGroups []string              `json:"additional_groups"` | ||||
| 	Config           *configs.Config       `json:"config"` | ||||
| 	Networks         []*network            `json:"network"` | ||||
| 	PassedFilesCount int                   `json:"passed_files_count"` | ||||
| 	ContainerId      string                `json:"containerid"` | ||||
| 	Rlimits          []configs.Rlimit      `json:"rlimits"` | ||||
| 	CreateConsole    bool                  `json:"create_console"` | ||||
| 	ConsoleWidth     uint16                `json:"console_width"` | ||||
| 	ConsoleHeight    uint16                `json:"console_height"` | ||||
| 	RootlessEUID     bool                  `json:"rootless_euid,omitempty"` | ||||
| 	RootlessCgroups  bool                  `json:"rootless_cgroups,omitempty"` | ||||
| 	SpecState        *specs.State          `json:"spec_state,omitempty"` | ||||
| 	Cgroup2Path      string                `json:"cgroup2_path,omitempty"` | ||||
| } | ||||
|  | ||||
| type initer interface { | ||||
| 	Init() error | ||||
| } | ||||
|  | ||||
| func newContainerInit(t initType, pipe *os.File, consoleSocket *os.File, fifoFd, logFd int, mountFds []int) (initer, error) { | ||||
| 	var config *initConfig | ||||
| 	if err := json.NewDecoder(pipe).Decode(&config); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if err := populateProcessEnvironment(config.Env); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// Clean the RLIMIT_NOFILE cache in go runtime. | ||||
| 	// Issue: https://github.com/opencontainers/runc/issues/4195 | ||||
| 	maybeClearRlimitNofileCache(config.Rlimits) | ||||
|  | ||||
| 	switch t { | ||||
| 	case initSetns: | ||||
| 		// mountFds must be nil in this case. We don't mount while doing runc exec. | ||||
| 		if mountFds != nil { | ||||
| 			return nil, errors.New("mountFds must be nil. Can't mount while doing runc exec.") | ||||
| 		} | ||||
|  | ||||
| 		return &linuxSetnsInit{ | ||||
| 			pipe:          pipe, | ||||
| 			consoleSocket: consoleSocket, | ||||
| 			config:        config, | ||||
| 			logFd:         logFd, | ||||
| 		}, nil | ||||
| 	case initStandard: | ||||
| 		return &linuxStandardInit{ | ||||
| 			pipe:          pipe, | ||||
| 			consoleSocket: consoleSocket, | ||||
| 			parentPid:     unix.Getppid(), | ||||
| 			config:        config, | ||||
| 			fifoFd:        fifoFd, | ||||
| 			logFd:         logFd, | ||||
| 			mountFds:      mountFds, | ||||
| 		}, nil | ||||
| 	} | ||||
| 	return nil, fmt.Errorf("unknown init type %q", t) | ||||
| } | ||||
|  | ||||
| // populateProcessEnvironment loads the provided environment variables into the | ||||
| // current processes's environment. | ||||
| func populateProcessEnvironment(env []string) error { | ||||
| 	for _, pair := range env { | ||||
| 		p := strings.SplitN(pair, "=", 2) | ||||
| 		if len(p) < 2 { | ||||
| 			return errors.New("invalid environment variable: missing '='") | ||||
| 		} | ||||
| 		name, val := p[0], p[1] | ||||
| 		if name == "" { | ||||
| 			return errors.New("invalid environment variable: name cannot be empty") | ||||
| 		} | ||||
| 		if strings.IndexByte(name, 0) >= 0 { | ||||
| 			return fmt.Errorf("invalid environment variable %q: name contains nul byte (\\x00)", name) | ||||
| 		} | ||||
| 		if strings.IndexByte(val, 0) >= 0 { | ||||
| 			return fmt.Errorf("invalid environment variable %q: value contains nul byte (\\x00)", name) | ||||
| 		} | ||||
| 		if err := os.Setenv(name, val); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // verifyCwd ensures that the current directory is actually inside the mount | ||||
| // namespace root of the current process. | ||||
| func verifyCwd() error { | ||||
| 	// getcwd(2) on Linux detects if cwd is outside of the rootfs of the | ||||
| 	// current mount namespace root, and in that case prefixes "(unreachable)" | ||||
| 	// to the returned string. glibc's getcwd(3) and Go's Getwd() both detect | ||||
| 	// when this happens and return ENOENT rather than returning a non-absolute | ||||
| 	// path. In both cases we can therefore easily detect if we have an invalid | ||||
| 	// cwd by checking the return value of getcwd(3). See getcwd(3) for more | ||||
| 	// details, and CVE-2024-21626 for the security issue that motivated this | ||||
| 	// check. | ||||
| 	// | ||||
| 	// We have to use unix.Getwd() here because os.Getwd() has a workaround for | ||||
| 	// $PWD which involves doing stat(.), which can fail if the current | ||||
| 	// directory is inaccessible to the container process. | ||||
| 	if wd, err := unix.Getwd(); errors.Is(err, unix.ENOENT) { | ||||
| 		return errors.New("current working directory is outside of container mount namespace root -- possible container breakout detected") | ||||
| 	} else if err != nil { | ||||
| 		return fmt.Errorf("failed to verify if current working directory is safe: %w", err) | ||||
| 	} else if !filepath.IsAbs(wd) { | ||||
| 		// We shouldn't ever hit this, but check just in case. | ||||
| 		return fmt.Errorf("current working directory is not absolute -- possible container breakout detected: cwd is %q", wd) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // finalizeNamespace drops the caps, sets the correct user | ||||
| // and working dir, and closes any leaked file descriptors | ||||
| // before executing the command inside the namespace | ||||
| func finalizeNamespace(config *initConfig) error { | ||||
| 	// Ensure that all unwanted fds we may have accidentally | ||||
| 	// inherited are marked close-on-exec so they stay out of the | ||||
| 	// container | ||||
| 	if err := utils.CloseExecFrom(config.PassedFilesCount + 3); err != nil { | ||||
| 		return fmt.Errorf("error closing exec fds: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// we only do chdir if it's specified | ||||
| 	doChdir := config.Cwd != "" | ||||
| 	if doChdir { | ||||
| 		// First, attempt the chdir before setting up the user. | ||||
| 		// This could allow us to access a directory that the user running runc can access | ||||
| 		// but the container user cannot. | ||||
| 		err := unix.Chdir(config.Cwd) | ||||
| 		switch { | ||||
| 		case err == nil: | ||||
| 			doChdir = false | ||||
| 		case os.IsPermission(err): | ||||
| 			// If we hit an EPERM, we should attempt again after setting up user. | ||||
| 			// This will allow us to successfully chdir if the container user has access | ||||
| 			// to the directory, but the user running runc does not. | ||||
| 			// This is useful in cases where the cwd is also a volume that's been chowned to the container user. | ||||
| 		default: | ||||
| 			return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %w", config.Cwd, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	caps := &configs.Capabilities{} | ||||
| 	if config.Capabilities != nil { | ||||
| 		caps = config.Capabilities | ||||
| 	} else if config.Config.Capabilities != nil { | ||||
| 		caps = config.Config.Capabilities | ||||
| 	} | ||||
| 	w, err := capabilities.New(caps) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	// drop capabilities in bounding set before changing user | ||||
| 	if err := w.ApplyBoundingSet(); err != nil { | ||||
| 		return fmt.Errorf("unable to apply bounding set: %w", err) | ||||
| 	} | ||||
| 	// preserve existing capabilities while we change users | ||||
| 	if err := system.SetKeepCaps(); err != nil { | ||||
| 		return fmt.Errorf("unable to set keep caps: %w", err) | ||||
| 	} | ||||
| 	if err := setupUser(config); err != nil { | ||||
| 		return fmt.Errorf("unable to setup user: %w", err) | ||||
| 	} | ||||
| 	// Change working directory AFTER the user has been set up, if we haven't done it yet. | ||||
| 	if doChdir { | ||||
| 		if err := unix.Chdir(config.Cwd); err != nil { | ||||
| 			return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %w", config.Cwd, err) | ||||
| 		} | ||||
| 	} | ||||
| 	// Make sure our final working directory is inside the container. | ||||
| 	if err := verifyCwd(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := system.ClearKeepCaps(); err != nil { | ||||
| 		return fmt.Errorf("unable to clear keep caps: %w", err) | ||||
| 	} | ||||
| 	if err := w.ApplyCaps(); err != nil { | ||||
| 		return fmt.Errorf("unable to apply caps: %w", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // setupConsole sets up the console from inside the container, and sends the | ||||
| // master pty fd to the config.Pipe (using cmsg). This is done to ensure that | ||||
| // consoles are scoped to a container properly (see runc#814 and the many | ||||
| // issues related to that). This has to be run *after* we've pivoted to the new | ||||
| // rootfs (and the users' configuration is entirely set up). | ||||
| func setupConsole(socket *os.File, config *initConfig, mount bool) error { | ||||
| 	defer socket.Close() | ||||
| 	// At this point, /dev/ptmx points to something that we would expect. We | ||||
| 	// used to change the owner of the slave path, but since the /dev/pts mount | ||||
| 	// can have gid=X set (at the users' option). So touching the owner of the | ||||
| 	// slave PTY is not necessary, as the kernel will handle that for us. Note | ||||
| 	// however, that setupUser (specifically fixStdioPermissions) *will* change | ||||
| 	// the UID owner of the console to be the user the process will run as (so | ||||
| 	// they can actually control their console). | ||||
|  | ||||
| 	pty, slavePath, err := console.NewPty() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// After we return from here, we don't need the console anymore. | ||||
| 	defer pty.Close() | ||||
|  | ||||
| 	if config.ConsoleHeight != 0 && config.ConsoleWidth != 0 { | ||||
| 		err = pty.Resize(console.WinSize{ | ||||
| 			Height: config.ConsoleHeight, | ||||
| 			Width:  config.ConsoleWidth, | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Mount the console inside our rootfs. | ||||
| 	if mount { | ||||
| 		if err := mountConsole(slavePath); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	// While we can access console.master, using the API is a good idea. | ||||
| 	if err := utils.SendFd(socket, pty.Name(), pty.Fd()); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	// Now, dup over all the things. | ||||
| 	return dupStdio(slavePath) | ||||
| } | ||||
|  | ||||
| // syncParentReady sends to the given pipe a JSON payload which indicates that | ||||
| // the init is ready to Exec the child process. It then waits for the parent to | ||||
| // indicate that it is cleared to Exec. | ||||
| func syncParentReady(pipe io.ReadWriter) error { | ||||
| 	// Tell parent. | ||||
| 	if err := writeSync(pipe, procReady); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Wait for parent to give the all-clear. | ||||
| 	return readSync(pipe, procRun) | ||||
| } | ||||
|  | ||||
| // syncParentHooks sends to the given pipe a JSON payload which indicates that | ||||
| // the parent should execute pre-start hooks. It then waits for the parent to | ||||
| // indicate that it is cleared to resume. | ||||
| func syncParentHooks(pipe io.ReadWriter) error { | ||||
| 	// Tell parent. | ||||
| 	if err := writeSync(pipe, procHooks); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Wait for parent to give the all-clear. | ||||
| 	return readSync(pipe, procResume) | ||||
| } | ||||
|  | ||||
| // syncParentSeccomp sends to the given pipe a JSON payload which | ||||
| // indicates that the parent should pick up the seccomp fd with pidfd_getfd() | ||||
| // and send it to the seccomp agent over a unix socket. It then waits for | ||||
| // the parent to indicate that it is cleared to resume and closes the seccompFd. | ||||
| // If the seccompFd is -1, there isn't anything to sync with the parent, so it | ||||
| // returns no error. | ||||
| func syncParentSeccomp(pipe io.ReadWriter, seccompFd int) error { | ||||
| 	if seccompFd == -1 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	// Tell parent. | ||||
| 	if err := writeSyncWithFd(pipe, procSeccomp, seccompFd); err != nil { | ||||
| 		unix.Close(seccompFd) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Wait for parent to give the all-clear. | ||||
| 	if err := readSync(pipe, procSeccompDone); err != nil { | ||||
| 		unix.Close(seccompFd) | ||||
| 		return fmt.Errorf("sync parent seccomp: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	if err := unix.Close(seccompFd); err != nil { | ||||
| 		return fmt.Errorf("close seccomp fd: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // setupUser changes the groups, gid, and uid for the user inside the container | ||||
| func setupUser(config *initConfig) error { | ||||
| 	// Set up defaults. | ||||
| 	defaultExecUser := user.ExecUser{ | ||||
| 		Uid:  0, | ||||
| 		Gid:  0, | ||||
| 		Home: "/", | ||||
| 	} | ||||
|  | ||||
| 	passwdPath, err := user.GetPasswdPath() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	groupPath, err := user.GetGroupPath() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	execUser, err := user.GetExecUserPath(config.User, &defaultExecUser, passwdPath, groupPath) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	var addGroups []int | ||||
| 	if len(config.AdditionalGroups) > 0 { | ||||
| 		addGroups, err = user.GetAdditionalGroupsPath(config.AdditionalGroups, groupPath) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Rather than just erroring out later in setuid(2) and setgid(2), check | ||||
| 	// that the user is mapped here. | ||||
| 	if _, err := config.Config.HostUID(execUser.Uid); err != nil { | ||||
| 		return errors.New("cannot set uid to unmapped user in user namespace") | ||||
| 	} | ||||
| 	if _, err := config.Config.HostGID(execUser.Gid); err != nil { | ||||
| 		return errors.New("cannot set gid to unmapped user in user namespace") | ||||
| 	} | ||||
|  | ||||
| 	if config.RootlessEUID { | ||||
| 		// We cannot set any additional groups in a rootless container and thus | ||||
| 		// we bail if the user asked us to do so. TODO: We currently can't do | ||||
| 		// this check earlier, but if libcontainer.Process.User was typesafe | ||||
| 		// this might work. | ||||
| 		if len(addGroups) > 0 { | ||||
| 			return errors.New("cannot set any additional groups in a rootless container") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Before we change to the container's user make sure that the processes | ||||
| 	// STDIO is correctly owned by the user that we are switching to. | ||||
| 	if err := fixStdioPermissions(execUser); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	setgroups, err := os.ReadFile("/proc/self/setgroups") | ||||
| 	if err != nil && !os.IsNotExist(err) { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// This isn't allowed in an unprivileged user namespace since Linux 3.19. | ||||
| 	// There's nothing we can do about /etc/group entries, so we silently | ||||
| 	// ignore setting groups here (since the user didn't explicitly ask us to | ||||
| 	// set the group). | ||||
| 	allowSupGroups := !config.RootlessEUID && string(bytes.TrimSpace(setgroups)) != "deny" | ||||
|  | ||||
| 	if allowSupGroups { | ||||
| 		suppGroups := append(execUser.Sgids, addGroups...) | ||||
| 		if err := unix.Setgroups(suppGroups); err != nil { | ||||
| 			return &os.SyscallError{Syscall: "setgroups", Err: err} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if err := system.Setgid(execUser.Gid); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := system.Setuid(execUser.Uid); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// if we didn't get HOME already, set it based on the user's HOME | ||||
| 	if envHome := os.Getenv("HOME"); envHome == "" { | ||||
| 		if err := os.Setenv("HOME", execUser.Home); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // fixStdioPermissions fixes the permissions of PID 1's STDIO within the container to the specified user. | ||||
| // The ownership needs to match because it is created outside of the container and needs to be | ||||
| // localized. | ||||
| func fixStdioPermissions(u *user.ExecUser) error { | ||||
| 	var null unix.Stat_t | ||||
| 	if err := unix.Stat("/dev/null", &null); err != nil { | ||||
| 		return &os.PathError{Op: "stat", Path: "/dev/null", Err: err} | ||||
| 	} | ||||
| 	for _, file := range []*os.File{os.Stdin, os.Stdout, os.Stderr} { | ||||
| 		var s unix.Stat_t | ||||
| 		if err := unix.Fstat(int(file.Fd()), &s); err != nil { | ||||
| 			return &os.PathError{Op: "fstat", Path: file.Name(), Err: err} | ||||
| 		} | ||||
|  | ||||
| 		// Skip chown if uid is already the one we want or any of the STDIO descriptors | ||||
| 		// were redirected to /dev/null. | ||||
| 		if int(s.Uid) == u.Uid || s.Rdev == null.Rdev { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		// We only change the uid (as it is possible for the mount to | ||||
| 		// prefer a different gid, and there's no reason for us to change it). | ||||
| 		// The reason why we don't just leave the default uid=X mount setup is | ||||
| 		// that users expect to be able to actually use their console. Without | ||||
| 		// this code, you couldn't effectively run as a non-root user inside a | ||||
| 		// container and also have a console set up. | ||||
| 		if err := file.Chown(u.Uid, int(s.Gid)); err != nil { | ||||
| 			// If we've hit an EINVAL then s.Gid isn't mapped in the user | ||||
| 			// namespace. If we've hit an EPERM then the inode's current owner | ||||
| 			// is not mapped in our user namespace (in particular, | ||||
| 			// privileged_wrt_inode_uidgid() has failed). Read-only | ||||
| 			// /dev can result in EROFS error. In any case, it's | ||||
| 			// better for us to just not touch the stdio rather | ||||
| 			// than bail at this point. | ||||
|  | ||||
| 			if errors.Is(err, unix.EINVAL) || errors.Is(err, unix.EPERM) || errors.Is(err, unix.EROFS) { | ||||
| 				continue | ||||
| 			} | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // setupNetwork sets up and initializes any network interface inside the container. | ||||
| func setupNetwork(config *initConfig) error { | ||||
| 	for _, config := range config.Networks { | ||||
| 		strategy, err := getStrategy(config.Type) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := strategy.initialize(config); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func setupRoute(config *configs.Config) error { | ||||
| 	for _, config := range config.Routes { | ||||
| 		_, dst, err := net.ParseCIDR(config.Destination) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		src := net.ParseIP(config.Source) | ||||
| 		if src == nil { | ||||
| 			return fmt.Errorf("Invalid source for route: %s", config.Source) | ||||
| 		} | ||||
| 		gw := net.ParseIP(config.Gateway) | ||||
| 		if gw == nil { | ||||
| 			return fmt.Errorf("Invalid gateway for route: %s", config.Gateway) | ||||
| 		} | ||||
| 		l, err := netlink.LinkByName(config.InterfaceName) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		route := &netlink.Route{ | ||||
| 			Scope:     netlink.SCOPE_UNIVERSE, | ||||
| 			Dst:       dst, | ||||
| 			Src:       src, | ||||
| 			Gw:        gw, | ||||
| 			LinkIndex: l.Attrs().Index, | ||||
| 		} | ||||
| 		if err := netlink.RouteAdd(route); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func maybeClearRlimitNofileCache(limits []configs.Rlimit) { | ||||
| 	for _, rlimit := range limits { | ||||
| 		if rlimit.Type == syscall.RLIMIT_NOFILE { | ||||
| 			system.ClearRlimitNofileCache(&syscall.Rlimit{ | ||||
| 				Cur: rlimit.Soft, | ||||
| 				Max: rlimit.Hard, | ||||
| 			}) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func setupRlimits(limits []configs.Rlimit, pid int) error { | ||||
| 	for _, rlimit := range limits { | ||||
| 		if err := unix.Prlimit(pid, rlimit.Type, &unix.Rlimit{Max: rlimit.Hard, Cur: rlimit.Soft}, nil); err != nil { | ||||
| 			return fmt.Errorf("error setting rlimit type %v: %w", rlimit.Type, err) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| const _P_PID = 1 | ||||
|  | ||||
| //nolint:structcheck,unused | ||||
| type siginfo struct { | ||||
| 	si_signo int32 | ||||
| 	si_errno int32 | ||||
| 	si_code  int32 | ||||
| 	// below here is a union; si_pid is the only field we use | ||||
| 	si_pid int32 | ||||
| 	// Pad to 128 bytes as detailed in blockUntilWaitable | ||||
| 	pad [96]byte | ||||
| } | ||||
|  | ||||
| // isWaitable returns true if the process has exited false otherwise. | ||||
| // Its based off blockUntilWaitable in src/os/wait_waitid.go | ||||
| func isWaitable(pid int) (bool, error) { | ||||
| 	si := &siginfo{} | ||||
| 	_, _, e := unix.Syscall6(unix.SYS_WAITID, _P_PID, uintptr(pid), uintptr(unsafe.Pointer(si)), unix.WEXITED|unix.WNOWAIT|unix.WNOHANG, 0, 0) | ||||
| 	if e != 0 { | ||||
| 		return false, &os.SyscallError{Syscall: "waitid", Err: e} | ||||
| 	} | ||||
|  | ||||
| 	return si.si_pid != 0, nil | ||||
| } | ||||
|  | ||||
| // signalAllProcesses freezes then iterates over all the processes inside the | ||||
| // manager's cgroups sending the signal s to them. | ||||
| // If s is SIGKILL then it will wait for each process to exit. | ||||
| // For all other signals it will check if the process is ready to report its | ||||
| // exit status and only if it is will a wait be performed. | ||||
| func signalAllProcesses(m cgroups.Manager, s os.Signal) error { | ||||
| 	var procs []*os.Process | ||||
| 	if err := m.Freeze(configs.Frozen); err != nil { | ||||
| 		logrus.Warn(err) | ||||
| 	} | ||||
| 	pids, err := m.GetAllPids() | ||||
| 	if err != nil { | ||||
| 		if err := m.Freeze(configs.Thawed); err != nil { | ||||
| 			logrus.Warn(err) | ||||
| 		} | ||||
| 		return err | ||||
| 	} | ||||
| 	for _, pid := range pids { | ||||
| 		p, err := os.FindProcess(pid) | ||||
| 		if err != nil { | ||||
| 			logrus.Warn(err) | ||||
| 			continue | ||||
| 		} | ||||
| 		procs = append(procs, p) | ||||
| 		if err := p.Signal(s); err != nil { | ||||
| 			logrus.Warn(err) | ||||
| 		} | ||||
| 	} | ||||
| 	if err := m.Freeze(configs.Thawed); err != nil { | ||||
| 		logrus.Warn(err) | ||||
| 	} | ||||
|  | ||||
| 	subreaper, err := system.GetSubreaper() | ||||
| 	if err != nil { | ||||
| 		// The error here means that PR_GET_CHILD_SUBREAPER is not | ||||
| 		// supported because this code might run on a kernel older | ||||
| 		// than 3.4. We don't want to throw an error in that case, | ||||
| 		// and we simplify things, considering there is no subreaper | ||||
| 		// set. | ||||
| 		subreaper = 0 | ||||
| 	} | ||||
|  | ||||
| 	for _, p := range procs { | ||||
| 		if s != unix.SIGKILL { | ||||
| 			if ok, err := isWaitable(p.Pid); err != nil { | ||||
| 				if !errors.Is(err, unix.ECHILD) { | ||||
| 					logrus.Warn("signalAllProcesses: ", p.Pid, err) | ||||
| 				} | ||||
| 				continue | ||||
| 			} else if !ok { | ||||
| 				// Not ready to report so don't wait | ||||
| 				continue | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// In case a subreaper has been setup, this code must not | ||||
| 		// wait for the process. Otherwise, we cannot be sure the | ||||
| 		// current process will be reaped by the subreaper, while | ||||
| 		// the subreaper might be waiting for this process in order | ||||
| 		// to retrieve its exit code. | ||||
| 		if subreaper == 0 { | ||||
| 			if _, err := p.Wait(); err != nil { | ||||
| 				if !errors.Is(err, unix.ECHILD) { | ||||
| 					logrus.Warn("wait: ", err) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										45
									
								
								vendor/github.com/opencontainers/runc/libcontainer/keys/keyctl.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										45
									
								
								vendor/github.com/opencontainers/runc/libcontainer/keys/keyctl.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,45 +0,0 @@ | ||||
| package keys | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| type KeySerial uint32 | ||||
|  | ||||
| func JoinSessionKeyring(name string) (KeySerial, error) { | ||||
| 	sessKeyID, err := unix.KeyctlJoinSessionKeyring(name) | ||||
| 	if err != nil { | ||||
| 		return 0, fmt.Errorf("unable to create session key: %w", err) | ||||
| 	} | ||||
| 	return KeySerial(sessKeyID), nil | ||||
| } | ||||
|  | ||||
| // ModKeyringPerm modifies permissions on a keyring by reading the current permissions, | ||||
| // anding the bits with the given mask (clearing permissions) and setting | ||||
| // additional permission bits | ||||
| func ModKeyringPerm(ringID KeySerial, mask, setbits uint32) error { | ||||
| 	dest, err := unix.KeyctlString(unix.KEYCTL_DESCRIBE, int(ringID)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	res := strings.Split(dest, ";") | ||||
| 	if len(res) < 5 { | ||||
| 		return errors.New("Destination buffer for key description is too small") | ||||
| 	} | ||||
|  | ||||
| 	// parse permissions | ||||
| 	perm64, err := strconv.ParseUint(res[3], 16, 32) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	perm := (uint32(perm64) & mask) | setbits | ||||
|  | ||||
| 	return unix.KeyctlSetperm(int(ringID), perm) | ||||
| } | ||||
							
								
								
									
										56
									
								
								vendor/github.com/opencontainers/runc/libcontainer/logs/logs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										56
									
								
								vendor/github.com/opencontainers/runc/libcontainer/logs/logs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,56 +0,0 @@ | ||||
| package logs | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"encoding/json" | ||||
| 	"io" | ||||
|  | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| func ForwardLogs(logPipe io.ReadCloser) chan error { | ||||
| 	done := make(chan error, 1) | ||||
| 	s := bufio.NewScanner(logPipe) | ||||
|  | ||||
| 	logger := logrus.StandardLogger() | ||||
| 	if logger.ReportCaller { | ||||
| 		// Need a copy of the standard logger, but with ReportCaller | ||||
| 		// turned off, as the logs are merely forwarded and their | ||||
| 		// true source is not this file/line/function. | ||||
| 		logNoCaller := *logrus.StandardLogger() | ||||
| 		logNoCaller.ReportCaller = false | ||||
| 		logger = &logNoCaller | ||||
| 	} | ||||
|  | ||||
| 	go func() { | ||||
| 		for s.Scan() { | ||||
| 			processEntry(s.Bytes(), logger) | ||||
| 		} | ||||
| 		if err := logPipe.Close(); err != nil { | ||||
| 			logrus.Errorf("error closing log source: %v", err) | ||||
| 		} | ||||
| 		// The only error we want to return is when reading from | ||||
| 		// logPipe has failed. | ||||
| 		done <- s.Err() | ||||
| 		close(done) | ||||
| 	}() | ||||
|  | ||||
| 	return done | ||||
| } | ||||
|  | ||||
| func processEntry(text []byte, logger *logrus.Logger) { | ||||
| 	if len(text) == 0 { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	var jl struct { | ||||
| 		Level logrus.Level `json:"level"` | ||||
| 		Msg   string       `json:"msg"` | ||||
| 	} | ||||
| 	if err := json.Unmarshal(text, &jl); err != nil { | ||||
| 		logrus.Errorf("failed to decode %q to json: %v", text, err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	logger.Log(jl.Level, jl.Msg) | ||||
| } | ||||
							
								
								
									
										97
									
								
								vendor/github.com/opencontainers/runc/libcontainer/message_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										97
									
								
								vendor/github.com/opencontainers/runc/libcontainer/message_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,97 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"math" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| // list of known message types we want to send to bootstrap program | ||||
| // The number is randomly chosen to not conflict with known netlink types | ||||
| const ( | ||||
| 	InitMsg          uint16 = 62000 | ||||
| 	CloneFlagsAttr   uint16 = 27281 | ||||
| 	NsPathsAttr      uint16 = 27282 | ||||
| 	UidmapAttr       uint16 = 27283 | ||||
| 	GidmapAttr       uint16 = 27284 | ||||
| 	SetgroupAttr     uint16 = 27285 | ||||
| 	OomScoreAdjAttr  uint16 = 27286 | ||||
| 	RootlessEUIDAttr uint16 = 27287 | ||||
| 	UidmapPathAttr   uint16 = 27288 | ||||
| 	GidmapPathAttr   uint16 = 27289 | ||||
| 	MountSourcesAttr uint16 = 27290 | ||||
| ) | ||||
|  | ||||
| type Int32msg struct { | ||||
| 	Type  uint16 | ||||
| 	Value uint32 | ||||
| } | ||||
|  | ||||
| // Serialize serializes the message. | ||||
| // Int32msg has the following representation | ||||
| // | nlattr len | nlattr type | | ||||
| // | uint32 value             | | ||||
| func (msg *Int32msg) Serialize() []byte { | ||||
| 	buf := make([]byte, msg.Len()) | ||||
| 	native := nl.NativeEndian() | ||||
| 	native.PutUint16(buf[0:2], uint16(msg.Len())) | ||||
| 	native.PutUint16(buf[2:4], msg.Type) | ||||
| 	native.PutUint32(buf[4:8], msg.Value) | ||||
| 	return buf | ||||
| } | ||||
|  | ||||
| func (msg *Int32msg) Len() int { | ||||
| 	return unix.NLA_HDRLEN + 4 | ||||
| } | ||||
|  | ||||
| // Bytemsg has the following representation | ||||
| // | nlattr len | nlattr type | | ||||
| // | value              | pad | | ||||
| type Bytemsg struct { | ||||
| 	Type  uint16 | ||||
| 	Value []byte | ||||
| } | ||||
|  | ||||
| func (msg *Bytemsg) Serialize() []byte { | ||||
| 	l := msg.Len() | ||||
| 	if l > math.MaxUint16 { | ||||
| 		// We cannot return nil nor an error here, so we panic with | ||||
| 		// a specific type instead, which is handled via recover in | ||||
| 		// bootstrapData. | ||||
| 		panic(netlinkError{fmt.Errorf("netlink: cannot serialize bytemsg of length %d (larger than UINT16_MAX)", l)}) | ||||
| 	} | ||||
| 	buf := make([]byte, (l+unix.NLA_ALIGNTO-1) & ^(unix.NLA_ALIGNTO-1)) | ||||
| 	native := nl.NativeEndian() | ||||
| 	native.PutUint16(buf[0:2], uint16(l)) | ||||
| 	native.PutUint16(buf[2:4], msg.Type) | ||||
| 	copy(buf[4:], msg.Value) | ||||
| 	return buf | ||||
| } | ||||
|  | ||||
| func (msg *Bytemsg) Len() int { | ||||
| 	return unix.NLA_HDRLEN + len(msg.Value) + 1 // null-terminated | ||||
| } | ||||
|  | ||||
| type Boolmsg struct { | ||||
| 	Type  uint16 | ||||
| 	Value bool | ||||
| } | ||||
|  | ||||
| func (msg *Boolmsg) Serialize() []byte { | ||||
| 	buf := make([]byte, msg.Len()) | ||||
| 	native := nl.NativeEndian() | ||||
| 	native.PutUint16(buf[0:2], uint16(msg.Len())) | ||||
| 	native.PutUint16(buf[2:4], msg.Type) | ||||
| 	if msg.Value { | ||||
| 		native.PutUint32(buf[4:8], uint32(1)) | ||||
| 	} else { | ||||
| 		native.PutUint32(buf[4:8], uint32(0)) | ||||
| 	} | ||||
| 	return buf | ||||
| } | ||||
|  | ||||
| func (msg *Boolmsg) Len() int { | ||||
| 	return unix.NLA_HDRLEN + 4 // alignment | ||||
| } | ||||
							
								
								
									
										101
									
								
								vendor/github.com/opencontainers/runc/libcontainer/mount_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										101
									
								
								vendor/github.com/opencontainers/runc/libcontainer/mount_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,101 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"io/fs" | ||||
| 	"strconv" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| // mountError holds an error from a failed mount or unmount operation. | ||||
| type mountError struct { | ||||
| 	op     string | ||||
| 	source string | ||||
| 	target string | ||||
| 	procfd string | ||||
| 	flags  uintptr | ||||
| 	data   string | ||||
| 	err    error | ||||
| } | ||||
|  | ||||
| // Error provides a string error representation. | ||||
| func (e *mountError) Error() string { | ||||
| 	out := e.op + " " | ||||
|  | ||||
| 	if e.source != "" { | ||||
| 		out += e.source + ":" + e.target | ||||
| 	} else { | ||||
| 		out += e.target | ||||
| 	} | ||||
| 	if e.procfd != "" { | ||||
| 		out += " (via " + e.procfd + ")" | ||||
| 	} | ||||
|  | ||||
| 	if e.flags != uintptr(0) { | ||||
| 		out += ", flags: 0x" + strconv.FormatUint(uint64(e.flags), 16) | ||||
| 	} | ||||
| 	if e.data != "" { | ||||
| 		out += ", data: " + e.data | ||||
| 	} | ||||
|  | ||||
| 	out += ": " + e.err.Error() | ||||
| 	return out | ||||
| } | ||||
|  | ||||
| // Unwrap returns the underlying error. | ||||
| // This is a convention used by Go 1.13+ standard library. | ||||
| func (e *mountError) Unwrap() error { | ||||
| 	return e.err | ||||
| } | ||||
|  | ||||
| // mount is a simple unix.Mount wrapper. If procfd is not empty, it is used | ||||
| // instead of target (and the target is only used to add context to an error). | ||||
| func mount(source, target, procfd, fstype string, flags uintptr, data string) error { | ||||
| 	dst := target | ||||
| 	if procfd != "" { | ||||
| 		dst = procfd | ||||
| 	} | ||||
| 	if err := unix.Mount(source, dst, fstype, flags, data); err != nil { | ||||
| 		return &mountError{ | ||||
| 			op:     "mount", | ||||
| 			source: source, | ||||
| 			target: target, | ||||
| 			procfd: procfd, | ||||
| 			flags:  flags, | ||||
| 			data:   data, | ||||
| 			err:    err, | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // unmount is a simple unix.Unmount wrapper. | ||||
| func unmount(target string, flags int) error { | ||||
| 	err := unix.Unmount(target, flags) | ||||
| 	if err != nil { | ||||
| 		return &mountError{ | ||||
| 			op:     "unmount", | ||||
| 			target: target, | ||||
| 			flags:  uintptr(flags), | ||||
| 			err:    err, | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // syscallMode returns the syscall-specific mode bits from Go's portable mode bits. | ||||
| // Copy from https://cs.opensource.google/go/go/+/refs/tags/go1.20.7:src/os/file_posix.go;l=61-75 | ||||
| func syscallMode(i fs.FileMode) (o uint32) { | ||||
| 	o |= uint32(i.Perm()) | ||||
| 	if i&fs.ModeSetuid != 0 { | ||||
| 		o |= unix.S_ISUID | ||||
| 	} | ||||
| 	if i&fs.ModeSetgid != 0 { | ||||
| 		o |= unix.S_ISGID | ||||
| 	} | ||||
| 	if i&fs.ModeSticky != 0 { | ||||
| 		o |= unix.S_ISVTX | ||||
| 	} | ||||
| 	// No mapping for Go's ModeTemporary (plan9 only). | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										100
									
								
								vendor/github.com/opencontainers/runc/libcontainer/network_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										100
									
								
								vendor/github.com/opencontainers/runc/libcontainer/network_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,100 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strconv" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs" | ||||
| 	"github.com/opencontainers/runc/types" | ||||
| 	"github.com/vishvananda/netlink" | ||||
| ) | ||||
|  | ||||
| var strategies = map[string]networkStrategy{ | ||||
| 	"loopback": &loopback{}, | ||||
| } | ||||
|  | ||||
| // networkStrategy represents a specific network configuration for | ||||
| // a container's networking stack | ||||
| type networkStrategy interface { | ||||
| 	create(*network, int) error | ||||
| 	initialize(*network) error | ||||
| 	detach(*configs.Network) error | ||||
| 	attach(*configs.Network) error | ||||
| } | ||||
|  | ||||
| // getStrategy returns the specific network strategy for the | ||||
| // provided type. | ||||
| func getStrategy(tpe string) (networkStrategy, error) { | ||||
| 	s, exists := strategies[tpe] | ||||
| 	if !exists { | ||||
| 		return nil, fmt.Errorf("unknown strategy type %q", tpe) | ||||
| 	} | ||||
| 	return s, nil | ||||
| } | ||||
|  | ||||
| // Returns the network statistics for the network interfaces represented by the NetworkRuntimeInfo. | ||||
| func getNetworkInterfaceStats(interfaceName string) (*types.NetworkInterface, error) { | ||||
| 	out := &types.NetworkInterface{Name: interfaceName} | ||||
| 	// This can happen if the network runtime information is missing - possible if the | ||||
| 	// container was created by an old version of libcontainer. | ||||
| 	if interfaceName == "" { | ||||
| 		return out, nil | ||||
| 	} | ||||
| 	type netStatsPair struct { | ||||
| 		// Where to write the output. | ||||
| 		Out *uint64 | ||||
| 		// The network stats file to read. | ||||
| 		File string | ||||
| 	} | ||||
| 	// Ingress for host veth is from the container. Hence tx_bytes stat on the host veth is actually number of bytes received by the container. | ||||
| 	netStats := []netStatsPair{ | ||||
| 		{Out: &out.RxBytes, File: "tx_bytes"}, | ||||
| 		{Out: &out.RxPackets, File: "tx_packets"}, | ||||
| 		{Out: &out.RxErrors, File: "tx_errors"}, | ||||
| 		{Out: &out.RxDropped, File: "tx_dropped"}, | ||||
|  | ||||
| 		{Out: &out.TxBytes, File: "rx_bytes"}, | ||||
| 		{Out: &out.TxPackets, File: "rx_packets"}, | ||||
| 		{Out: &out.TxErrors, File: "rx_errors"}, | ||||
| 		{Out: &out.TxDropped, File: "rx_dropped"}, | ||||
| 	} | ||||
| 	for _, netStat := range netStats { | ||||
| 		data, err := readSysfsNetworkStats(interfaceName, netStat.File) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		*(netStat.Out) = data | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| // Reads the specified statistics available under /sys/class/net/<EthInterface>/statistics | ||||
| func readSysfsNetworkStats(ethInterface, statsFile string) (uint64, error) { | ||||
| 	data, err := os.ReadFile(filepath.Join("/sys/class/net", ethInterface, "statistics", statsFile)) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	return strconv.ParseUint(string(bytes.TrimSpace(data)), 10, 64) | ||||
| } | ||||
|  | ||||
| // loopback is a network strategy that provides a basic loopback device | ||||
| type loopback struct{} | ||||
|  | ||||
| func (l *loopback) create(n *network, nspid int) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (l *loopback) initialize(config *network) error { | ||||
| 	return netlink.LinkSetUp(&netlink.Device{LinkAttrs: netlink.LinkAttrs{Name: "lo"}}) | ||||
| } | ||||
|  | ||||
| func (l *loopback) attach(n *configs.Network) (err error) { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (l *loopback) detach(n *configs.Network) (err error) { | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										84
									
								
								vendor/github.com/opencontainers/runc/libcontainer/notify_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										84
									
								
								vendor/github.com/opencontainers/runc/libcontainer/notify_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,84 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| type PressureLevel uint | ||||
|  | ||||
| const ( | ||||
| 	LowPressure PressureLevel = iota | ||||
| 	MediumPressure | ||||
| 	CriticalPressure | ||||
| ) | ||||
|  | ||||
| func registerMemoryEvent(cgDir string, evName string, arg string) (<-chan struct{}, error) { | ||||
| 	evFile, err := os.Open(filepath.Join(cgDir, evName)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	fd, err := unix.Eventfd(0, unix.EFD_CLOEXEC) | ||||
| 	if err != nil { | ||||
| 		evFile.Close() | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	eventfd := os.NewFile(uintptr(fd), "eventfd") | ||||
|  | ||||
| 	eventControlPath := filepath.Join(cgDir, "cgroup.event_control") | ||||
| 	data := fmt.Sprintf("%d %d %s", eventfd.Fd(), evFile.Fd(), arg) | ||||
| 	if err := os.WriteFile(eventControlPath, []byte(data), 0o700); err != nil { | ||||
| 		eventfd.Close() | ||||
| 		evFile.Close() | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	ch := make(chan struct{}) | ||||
| 	go func() { | ||||
| 		defer func() { | ||||
| 			eventfd.Close() | ||||
| 			evFile.Close() | ||||
| 			close(ch) | ||||
| 		}() | ||||
| 		buf := make([]byte, 8) | ||||
| 		for { | ||||
| 			if _, err := eventfd.Read(buf); err != nil { | ||||
| 				return | ||||
| 			} | ||||
| 			// When a cgroup is destroyed, an event is sent to eventfd. | ||||
| 			// So if the control path is gone, return instead of notifying. | ||||
| 			if _, err := os.Lstat(eventControlPath); os.IsNotExist(err) { | ||||
| 				return | ||||
| 			} | ||||
| 			ch <- struct{}{} | ||||
| 		} | ||||
| 	}() | ||||
| 	return ch, nil | ||||
| } | ||||
|  | ||||
| // notifyOnOOM returns channel on which you can expect event about OOM, | ||||
| // if process died without OOM this channel will be closed. | ||||
| func notifyOnOOM(dir string) (<-chan struct{}, error) { | ||||
| 	if dir == "" { | ||||
| 		return nil, errors.New("memory controller missing") | ||||
| 	} | ||||
|  | ||||
| 	return registerMemoryEvent(dir, "memory.oom_control", "") | ||||
| } | ||||
|  | ||||
| func notifyMemoryPressure(dir string, level PressureLevel) (<-chan struct{}, error) { | ||||
| 	if dir == "" { | ||||
| 		return nil, errors.New("memory controller missing") | ||||
| 	} | ||||
|  | ||||
| 	if level > CriticalPressure { | ||||
| 		return nil, fmt.Errorf("invalid pressure level %d", level) | ||||
| 	} | ||||
|  | ||||
| 	levelStr := []string{"low", "medium", "critical"}[level] | ||||
| 	return registerMemoryEvent(dir, "memory.pressure_level", levelStr) | ||||
| } | ||||
							
								
								
									
										80
									
								
								vendor/github.com/opencontainers/runc/libcontainer/notify_v2_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										80
									
								
								vendor/github.com/opencontainers/runc/libcontainer/notify_v2_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,80 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"path/filepath" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| func registerMemoryEventV2(cgDir, evName, cgEvName string) (<-chan struct{}, error) { | ||||
| 	fd, err := unix.InotifyInit() | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("unable to init inotify: %w", err) | ||||
| 	} | ||||
| 	// watching oom kill | ||||
| 	evFd, err := unix.InotifyAddWatch(fd, filepath.Join(cgDir, evName), unix.IN_MODIFY) | ||||
| 	if err != nil { | ||||
| 		unix.Close(fd) | ||||
| 		return nil, fmt.Errorf("unable to add inotify watch: %w", err) | ||||
| 	} | ||||
| 	// Because no `unix.IN_DELETE|unix.IN_DELETE_SELF` event for cgroup file system, so watching all process exited | ||||
| 	cgFd, err := unix.InotifyAddWatch(fd, filepath.Join(cgDir, cgEvName), unix.IN_MODIFY) | ||||
| 	if err != nil { | ||||
| 		unix.Close(fd) | ||||
| 		return nil, fmt.Errorf("unable to add inotify watch: %w", err) | ||||
| 	} | ||||
| 	ch := make(chan struct{}) | ||||
| 	go func() { | ||||
| 		var ( | ||||
| 			buffer [unix.SizeofInotifyEvent + unix.PathMax + 1]byte | ||||
| 			offset uint32 | ||||
| 		) | ||||
| 		defer func() { | ||||
| 			unix.Close(fd) | ||||
| 			close(ch) | ||||
| 		}() | ||||
|  | ||||
| 		for { | ||||
| 			n, err := unix.Read(fd, buffer[:]) | ||||
| 			if err != nil { | ||||
| 				logrus.Warnf("unable to read event data from inotify, got error: %v", err) | ||||
| 				return | ||||
| 			} | ||||
| 			if n < unix.SizeofInotifyEvent { | ||||
| 				logrus.Warnf("we should read at least %d bytes from inotify, but got %d bytes.", unix.SizeofInotifyEvent, n) | ||||
| 				return | ||||
| 			} | ||||
| 			offset = 0 | ||||
| 			for offset <= uint32(n-unix.SizeofInotifyEvent) { | ||||
| 				rawEvent := (*unix.InotifyEvent)(unsafe.Pointer(&buffer[offset])) | ||||
| 				offset += unix.SizeofInotifyEvent + rawEvent.Len | ||||
| 				if rawEvent.Mask&unix.IN_MODIFY != unix.IN_MODIFY { | ||||
| 					continue | ||||
| 				} | ||||
| 				switch int(rawEvent.Wd) { | ||||
| 				case evFd: | ||||
| 					oom, err := fscommon.GetValueByKey(cgDir, evName, "oom_kill") | ||||
| 					if err != nil || oom > 0 { | ||||
| 						ch <- struct{}{} | ||||
| 					} | ||||
| 				case cgFd: | ||||
| 					pids, err := fscommon.GetValueByKey(cgDir, cgEvName, "populated") | ||||
| 					if err != nil || pids == 0 { | ||||
| 						return | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
| 	return ch, nil | ||||
| } | ||||
|  | ||||
| // notifyOnOOMV2 returns channel on which you can expect event about OOM, | ||||
| // if process died without OOM this channel will be closed. | ||||
| func notifyOnOOMV2(path string) (<-chan struct{}, error) { | ||||
| 	return registerMemoryEventV2(path, "memory.events", "cgroup.events") | ||||
| } | ||||
							
								
								
									
										126
									
								
								vendor/github.com/opencontainers/runc/libcontainer/process.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										126
									
								
								vendor/github.com/opencontainers/runc/libcontainer/process.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,126 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"math" | ||||
| 	"os" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs" | ||||
| ) | ||||
|  | ||||
| var errInvalidProcess = errors.New("invalid process") | ||||
|  | ||||
| type processOperations interface { | ||||
| 	wait() (*os.ProcessState, error) | ||||
| 	signal(sig os.Signal) error | ||||
| 	pid() int | ||||
| } | ||||
|  | ||||
| // Process specifies the configuration and IO for a process inside | ||||
| // a container. | ||||
| type Process struct { | ||||
| 	// The command to be run followed by any arguments. | ||||
| 	Args []string | ||||
|  | ||||
| 	// Env specifies the environment variables for the process. | ||||
| 	Env []string | ||||
|  | ||||
| 	// User will set the uid and gid of the executing process running inside the container | ||||
| 	// local to the container's user and group configuration. | ||||
| 	User string | ||||
|  | ||||
| 	// AdditionalGroups specifies the gids that should be added to supplementary groups | ||||
| 	// in addition to those that the user belongs to. | ||||
| 	AdditionalGroups []string | ||||
|  | ||||
| 	// Cwd will change the processes current working directory inside the container's rootfs. | ||||
| 	Cwd string | ||||
|  | ||||
| 	// Stdin is a pointer to a reader which provides the standard input stream. | ||||
| 	Stdin io.Reader | ||||
|  | ||||
| 	// Stdout is a pointer to a writer which receives the standard output stream. | ||||
| 	Stdout io.Writer | ||||
|  | ||||
| 	// Stderr is a pointer to a writer which receives the standard error stream. | ||||
| 	Stderr io.Writer | ||||
|  | ||||
| 	// ExtraFiles specifies additional open files to be inherited by the container | ||||
| 	ExtraFiles []*os.File | ||||
|  | ||||
| 	// Initial sizings for the console | ||||
| 	ConsoleWidth  uint16 | ||||
| 	ConsoleHeight uint16 | ||||
|  | ||||
| 	// Capabilities specify the capabilities to keep when executing the process inside the container | ||||
| 	// All capabilities not specified will be dropped from the processes capability mask | ||||
| 	Capabilities *configs.Capabilities | ||||
|  | ||||
| 	// AppArmorProfile specifies the profile to apply to the process and is | ||||
| 	// changed at the time the process is execed | ||||
| 	AppArmorProfile string | ||||
|  | ||||
| 	// Label specifies the label to apply to the process.  It is commonly used by selinux | ||||
| 	Label string | ||||
|  | ||||
| 	// NoNewPrivileges controls whether processes can gain additional privileges. | ||||
| 	NoNewPrivileges *bool | ||||
|  | ||||
| 	// Rlimits specifies the resource limits, such as max open files, to set in the container | ||||
| 	// If Rlimits are not set, the container will inherit rlimits from the parent process | ||||
| 	Rlimits []configs.Rlimit | ||||
|  | ||||
| 	// ConsoleSocket provides the masterfd console. | ||||
| 	ConsoleSocket *os.File | ||||
|  | ||||
| 	// Init specifies whether the process is the first process in the container. | ||||
| 	Init bool | ||||
|  | ||||
| 	ops processOperations | ||||
|  | ||||
| 	LogLevel string | ||||
|  | ||||
| 	// SubCgroupPaths specifies sub-cgroups to run the process in. | ||||
| 	// Map keys are controller names, map values are paths (relative to | ||||
| 	// container's top-level cgroup). | ||||
| 	// | ||||
| 	// If empty, the default top-level container's cgroup is used. | ||||
| 	// | ||||
| 	// For cgroup v2, the only key allowed is "". | ||||
| 	SubCgroupPaths map[string]string | ||||
| } | ||||
|  | ||||
| // Wait waits for the process to exit. | ||||
| // Wait releases any resources associated with the Process | ||||
| func (p Process) Wait() (*os.ProcessState, error) { | ||||
| 	if p.ops == nil { | ||||
| 		return nil, errInvalidProcess | ||||
| 	} | ||||
| 	return p.ops.wait() | ||||
| } | ||||
|  | ||||
| // Pid returns the process ID | ||||
| func (p Process) Pid() (int, error) { | ||||
| 	// math.MinInt32 is returned here, because it's invalid value | ||||
| 	// for the kill() system call. | ||||
| 	if p.ops == nil { | ||||
| 		return math.MinInt32, errInvalidProcess | ||||
| 	} | ||||
| 	return p.ops.pid(), nil | ||||
| } | ||||
|  | ||||
| // Signal sends a signal to the Process. | ||||
| func (p Process) Signal(sig os.Signal) error { | ||||
| 	if p.ops == nil { | ||||
| 		return errInvalidProcess | ||||
| 	} | ||||
| 	return p.ops.signal(sig) | ||||
| } | ||||
|  | ||||
| // IO holds the process's STDIO | ||||
| type IO struct { | ||||
| 	Stdin  io.WriteCloser | ||||
| 	Stdout io.ReadCloser | ||||
| 	Stderr io.ReadCloser | ||||
| } | ||||
							
								
								
									
										823
									
								
								vendor/github.com/opencontainers/runc/libcontainer/process_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										823
									
								
								vendor/github.com/opencontainers/runc/libcontainer/process_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,823 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"path/filepath" | ||||
| 	"strconv" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/cgroups" | ||||
| 	"github.com/opencontainers/runc/libcontainer/cgroups/fs2" | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs" | ||||
| 	"github.com/opencontainers/runc/libcontainer/intelrdt" | ||||
| 	"github.com/opencontainers/runc/libcontainer/logs" | ||||
| 	"github.com/opencontainers/runc/libcontainer/system" | ||||
| 	"github.com/opencontainers/runc/libcontainer/utils" | ||||
| 	"github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| type parentProcess interface { | ||||
| 	// pid returns the pid for the running process. | ||||
| 	pid() int | ||||
|  | ||||
| 	// start starts the process execution. | ||||
| 	start() error | ||||
|  | ||||
| 	// send a SIGKILL to the process and wait for the exit. | ||||
| 	terminate() error | ||||
|  | ||||
| 	// wait waits on the process returning the process state. | ||||
| 	wait() (*os.ProcessState, error) | ||||
|  | ||||
| 	// startTime returns the process start time. | ||||
| 	startTime() (uint64, error) | ||||
| 	signal(os.Signal) error | ||||
| 	externalDescriptors() []string | ||||
| 	setExternalDescriptors(fds []string) | ||||
| 	forwardChildLogs() chan error | ||||
| } | ||||
|  | ||||
| type filePair struct { | ||||
| 	parent *os.File | ||||
| 	child  *os.File | ||||
| } | ||||
|  | ||||
| type setnsProcess struct { | ||||
| 	cmd             *exec.Cmd | ||||
| 	messageSockPair filePair | ||||
| 	logFilePair     filePair | ||||
| 	cgroupPaths     map[string]string | ||||
| 	rootlessCgroups bool | ||||
| 	manager         cgroups.Manager | ||||
| 	intelRdtPath    string | ||||
| 	config          *initConfig | ||||
| 	fds             []string | ||||
| 	process         *Process | ||||
| 	bootstrapData   io.Reader | ||||
| 	initProcessPid  int | ||||
| } | ||||
|  | ||||
| func (p *setnsProcess) startTime() (uint64, error) { | ||||
| 	stat, err := system.Stat(p.pid()) | ||||
| 	return stat.StartTime, err | ||||
| } | ||||
|  | ||||
| func (p *setnsProcess) signal(sig os.Signal) error { | ||||
| 	s, ok := sig.(unix.Signal) | ||||
| 	if !ok { | ||||
| 		return errors.New("os: unsupported signal type") | ||||
| 	} | ||||
| 	return unix.Kill(p.pid(), s) | ||||
| } | ||||
|  | ||||
| func (p *setnsProcess) start() (retErr error) { | ||||
| 	defer p.messageSockPair.parent.Close() | ||||
| 	// get the "before" value of oom kill count | ||||
| 	oom, _ := p.manager.OOMKillCount() | ||||
| 	err := p.cmd.Start() | ||||
| 	// close the write-side of the pipes (controlled by child) | ||||
| 	p.messageSockPair.child.Close() | ||||
| 	p.logFilePair.child.Close() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("error starting setns process: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	waitInit := initWaiter(p.messageSockPair.parent) | ||||
| 	defer func() { | ||||
| 		if retErr != nil { | ||||
| 			if newOom, err := p.manager.OOMKillCount(); err == nil && newOom != oom { | ||||
| 				// Someone in this cgroup was killed, this _might_ be us. | ||||
| 				retErr = fmt.Errorf("%w (possibly OOM-killed)", retErr) | ||||
| 			} | ||||
| 			werr := <-waitInit | ||||
| 			if werr != nil { | ||||
| 				logrus.WithError(werr).Warn() | ||||
| 			} | ||||
| 			err := ignoreTerminateErrors(p.terminate()) | ||||
| 			if err != nil { | ||||
| 				logrus.WithError(err).Warn("unable to terminate setnsProcess") | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	if p.bootstrapData != nil { | ||||
| 		if _, err := io.Copy(p.messageSockPair.parent, p.bootstrapData); err != nil { | ||||
| 			return fmt.Errorf("error copying bootstrap data to pipe: %w", err) | ||||
| 		} | ||||
| 	} | ||||
| 	err = <-waitInit | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := p.execSetns(); err != nil { | ||||
| 		return fmt.Errorf("error executing setns process: %w", err) | ||||
| 	} | ||||
| 	for _, path := range p.cgroupPaths { | ||||
| 		if err := cgroups.WriteCgroupProc(path, p.pid()); err != nil && !p.rootlessCgroups { | ||||
| 			// On cgroup v2 + nesting + domain controllers, WriteCgroupProc may fail with EBUSY. | ||||
| 			// https://github.com/opencontainers/runc/issues/2356#issuecomment-621277643 | ||||
| 			// Try to join the cgroup of InitProcessPid. | ||||
| 			if cgroups.IsCgroup2UnifiedMode() && p.initProcessPid != 0 { | ||||
| 				initProcCgroupFile := fmt.Sprintf("/proc/%d/cgroup", p.initProcessPid) | ||||
| 				initCg, initCgErr := cgroups.ParseCgroupFile(initProcCgroupFile) | ||||
| 				if initCgErr == nil { | ||||
| 					if initCgPath, ok := initCg[""]; ok { | ||||
| 						initCgDirpath := filepath.Join(fs2.UnifiedMountpoint, initCgPath) | ||||
| 						logrus.Debugf("adding pid %d to cgroups %v failed (%v), attempting to join %q (obtained from %s)", | ||||
| 							p.pid(), p.cgroupPaths, err, initCg, initCgDirpath) | ||||
| 						// NOTE: initCgDirPath is not guaranteed to exist because we didn't pause the container. | ||||
| 						err = cgroups.WriteCgroupProc(initCgDirpath, p.pid()) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("error adding pid %d to cgroups: %w", p.pid(), err) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	if p.intelRdtPath != "" { | ||||
| 		// if Intel RDT "resource control" filesystem path exists | ||||
| 		_, err := os.Stat(p.intelRdtPath) | ||||
| 		if err == nil { | ||||
| 			if err := intelrdt.WriteIntelRdtTasks(p.intelRdtPath, p.pid()); err != nil { | ||||
| 				return fmt.Errorf("error adding pid %d to Intel RDT: %w", p.pid(), err) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if err := utils.WriteJSON(p.messageSockPair.parent, p.config); err != nil { | ||||
| 		return fmt.Errorf("error writing config to pipe: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	ierr := parseSync(p.messageSockPair.parent, func(sync *syncT) error { | ||||
| 		switch sync.Type { | ||||
| 		case procReady: | ||||
| 			// Set rlimits, this has to be done here because we lose permissions | ||||
| 			// to raise the limits once we enter a user-namespace | ||||
| 			if err := setupRlimits(p.config.Rlimits, p.pid()); err != nil { | ||||
| 				return fmt.Errorf("error setting rlimits for ready process: %w", err) | ||||
| 			} | ||||
|  | ||||
| 			// Sync with child. | ||||
| 			return writeSync(p.messageSockPair.parent, procRun) | ||||
| 		case procHooks: | ||||
| 			// This shouldn't happen. | ||||
| 			panic("unexpected procHooks in setns") | ||||
| 		case procSeccomp: | ||||
| 			if p.config.Config.Seccomp.ListenerPath == "" { | ||||
| 				return errors.New("listenerPath is not set") | ||||
| 			} | ||||
|  | ||||
| 			seccompFd, err := recvSeccompFd(uintptr(p.pid()), uintptr(sync.Fd)) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			defer unix.Close(seccompFd) | ||||
|  | ||||
| 			bundle, annotations := utils.Annotations(p.config.Config.Labels) | ||||
| 			containerProcessState := &specs.ContainerProcessState{ | ||||
| 				Version:  specs.Version, | ||||
| 				Fds:      []string{specs.SeccompFdName}, | ||||
| 				Pid:      p.cmd.Process.Pid, | ||||
| 				Metadata: p.config.Config.Seccomp.ListenerMetadata, | ||||
| 				State: specs.State{ | ||||
| 					Version:     specs.Version, | ||||
| 					ID:          p.config.ContainerId, | ||||
| 					Status:      specs.StateRunning, | ||||
| 					Pid:         p.initProcessPid, | ||||
| 					Bundle:      bundle, | ||||
| 					Annotations: annotations, | ||||
| 				}, | ||||
| 			} | ||||
| 			if err := sendContainerProcessState(p.config.Config.Seccomp.ListenerPath, | ||||
| 				containerProcessState, seccompFd); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
|  | ||||
| 			// Sync with child. | ||||
| 			if err := writeSync(p.messageSockPair.parent, procSeccompDone); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			return nil | ||||
| 		default: | ||||
| 			return errors.New("invalid JSON payload from child") | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	if err := unix.Shutdown(int(p.messageSockPair.parent.Fd()), unix.SHUT_WR); err != nil { | ||||
| 		return &os.PathError{Op: "shutdown", Path: "(init pipe)", Err: err} | ||||
| 	} | ||||
| 	// Must be done after Shutdown so the child will exit and we can wait for it. | ||||
| 	if ierr != nil { | ||||
| 		_, _ = p.wait() | ||||
| 		return ierr | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // execSetns runs the process that executes C code to perform the setns calls | ||||
| // because setns support requires the C process to fork off a child and perform the setns | ||||
| // before the go runtime boots, we wait on the process to die and receive the child's pid | ||||
| // over the provided pipe. | ||||
| func (p *setnsProcess) execSetns() error { | ||||
| 	status, err := p.cmd.Process.Wait() | ||||
| 	if err != nil { | ||||
| 		_ = p.cmd.Wait() | ||||
| 		return fmt.Errorf("error waiting on setns process to finish: %w", err) | ||||
| 	} | ||||
| 	if !status.Success() { | ||||
| 		_ = p.cmd.Wait() | ||||
| 		return &exec.ExitError{ProcessState: status} | ||||
| 	} | ||||
| 	var pid *pid | ||||
| 	if err := json.NewDecoder(p.messageSockPair.parent).Decode(&pid); err != nil { | ||||
| 		_ = p.cmd.Wait() | ||||
| 		return fmt.Errorf("error reading pid from init pipe: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// Clean up the zombie parent process | ||||
| 	// On Unix systems FindProcess always succeeds. | ||||
| 	firstChildProcess, _ := os.FindProcess(pid.PidFirstChild) | ||||
|  | ||||
| 	// Ignore the error in case the child has already been reaped for any reason | ||||
| 	_, _ = firstChildProcess.Wait() | ||||
|  | ||||
| 	process, err := os.FindProcess(pid.Pid) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	p.cmd.Process = process | ||||
| 	p.process.ops = p | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // terminate sends a SIGKILL to the forked process for the setns routine then waits to | ||||
| // avoid the process becoming a zombie. | ||||
| func (p *setnsProcess) terminate() error { | ||||
| 	if p.cmd.Process == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	err := p.cmd.Process.Kill() | ||||
| 	if _, werr := p.wait(); err == nil { | ||||
| 		err = werr | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func (p *setnsProcess) wait() (*os.ProcessState, error) { | ||||
| 	err := p.cmd.Wait() | ||||
|  | ||||
| 	// Return actual ProcessState even on Wait error | ||||
| 	return p.cmd.ProcessState, err | ||||
| } | ||||
|  | ||||
| func (p *setnsProcess) pid() int { | ||||
| 	return p.cmd.Process.Pid | ||||
| } | ||||
|  | ||||
| func (p *setnsProcess) externalDescriptors() []string { | ||||
| 	return p.fds | ||||
| } | ||||
|  | ||||
| func (p *setnsProcess) setExternalDescriptors(newFds []string) { | ||||
| 	p.fds = newFds | ||||
| } | ||||
|  | ||||
| func (p *setnsProcess) forwardChildLogs() chan error { | ||||
| 	return logs.ForwardLogs(p.logFilePair.parent) | ||||
| } | ||||
|  | ||||
| type initProcess struct { | ||||
| 	cmd             *exec.Cmd | ||||
| 	messageSockPair filePair | ||||
| 	logFilePair     filePair | ||||
| 	config          *initConfig | ||||
| 	manager         cgroups.Manager | ||||
| 	intelRdtManager *intelrdt.Manager | ||||
| 	container       *linuxContainer | ||||
| 	fds             []string | ||||
| 	process         *Process | ||||
| 	bootstrapData   io.Reader | ||||
| 	sharePidns      bool | ||||
| } | ||||
|  | ||||
| func (p *initProcess) pid() int { | ||||
| 	return p.cmd.Process.Pid | ||||
| } | ||||
|  | ||||
| func (p *initProcess) externalDescriptors() []string { | ||||
| 	return p.fds | ||||
| } | ||||
|  | ||||
| // getChildPid receives the final child's pid over the provided pipe. | ||||
| func (p *initProcess) getChildPid() (int, error) { | ||||
| 	var pid pid | ||||
| 	if err := json.NewDecoder(p.messageSockPair.parent).Decode(&pid); err != nil { | ||||
| 		_ = p.cmd.Wait() | ||||
| 		return -1, err | ||||
| 	} | ||||
|  | ||||
| 	// Clean up the zombie parent process | ||||
| 	// On Unix systems FindProcess always succeeds. | ||||
| 	firstChildProcess, _ := os.FindProcess(pid.PidFirstChild) | ||||
|  | ||||
| 	// Ignore the error in case the child has already been reaped for any reason | ||||
| 	_, _ = firstChildProcess.Wait() | ||||
|  | ||||
| 	return pid.Pid, nil | ||||
| } | ||||
|  | ||||
| func (p *initProcess) waitForChildExit(childPid int) error { | ||||
| 	status, err := p.cmd.Process.Wait() | ||||
| 	if err != nil { | ||||
| 		_ = p.cmd.Wait() | ||||
| 		return err | ||||
| 	} | ||||
| 	if !status.Success() { | ||||
| 		_ = p.cmd.Wait() | ||||
| 		return &exec.ExitError{ProcessState: status} | ||||
| 	} | ||||
|  | ||||
| 	process, err := os.FindProcess(childPid) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	p.cmd.Process = process | ||||
| 	p.process.ops = p | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *initProcess) start() (retErr error) { | ||||
| 	defer p.messageSockPair.parent.Close() //nolint: errcheck | ||||
| 	err := p.cmd.Start() | ||||
| 	p.process.ops = p | ||||
| 	// close the write-side of the pipes (controlled by child) | ||||
| 	_ = p.messageSockPair.child.Close() | ||||
| 	_ = p.logFilePair.child.Close() | ||||
| 	if err != nil { | ||||
| 		p.process.ops = nil | ||||
| 		return fmt.Errorf("unable to start init: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	waitInit := initWaiter(p.messageSockPair.parent) | ||||
| 	defer func() { | ||||
| 		if retErr != nil { | ||||
| 			// Find out if init is killed by the kernel's OOM killer. | ||||
| 			// Get the count before killing init as otherwise cgroup | ||||
| 			// might be removed by systemd. | ||||
| 			oom, err := p.manager.OOMKillCount() | ||||
| 			if err != nil { | ||||
| 				logrus.WithError(err).Warn("unable to get oom kill count") | ||||
| 			} else if oom > 0 { | ||||
| 				// Does not matter what the particular error was, | ||||
| 				// its cause is most probably OOM, so report that. | ||||
| 				const oomError = "container init was OOM-killed (memory limit too low?)" | ||||
|  | ||||
| 				if logrus.GetLevel() >= logrus.DebugLevel { | ||||
| 					// Only show the original error if debug is set, | ||||
| 					// as it is not generally very useful. | ||||
| 					retErr = fmt.Errorf(oomError+": %w", retErr) | ||||
| 				} else { | ||||
| 					retErr = errors.New(oomError) | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			werr := <-waitInit | ||||
| 			if werr != nil { | ||||
| 				logrus.WithError(werr).Warn() | ||||
| 			} | ||||
|  | ||||
| 			// Terminate the process to ensure we can remove cgroups. | ||||
| 			if err := ignoreTerminateErrors(p.terminate()); err != nil { | ||||
| 				logrus.WithError(err).Warn("unable to terminate initProcess") | ||||
| 			} | ||||
|  | ||||
| 			_ = p.manager.Destroy() | ||||
| 			if p.intelRdtManager != nil { | ||||
| 				_ = p.intelRdtManager.Destroy() | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	// Do this before syncing with child so that no children can escape the | ||||
| 	// cgroup. We don't need to worry about not doing this and not being root | ||||
| 	// because we'd be using the rootless cgroup manager in that case. | ||||
| 	if err := p.manager.Apply(p.pid()); err != nil { | ||||
| 		return fmt.Errorf("unable to apply cgroup configuration: %w", err) | ||||
| 	} | ||||
| 	if p.intelRdtManager != nil { | ||||
| 		if err := p.intelRdtManager.Apply(p.pid()); err != nil { | ||||
| 			return fmt.Errorf("unable to apply Intel RDT configuration: %w", err) | ||||
| 		} | ||||
| 	} | ||||
| 	if _, err := io.Copy(p.messageSockPair.parent, p.bootstrapData); err != nil { | ||||
| 		return fmt.Errorf("can't copy bootstrap data to pipe: %w", err) | ||||
| 	} | ||||
| 	err = <-waitInit | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	childPid, err := p.getChildPid() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("can't get final child's PID from pipe: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// Save the standard descriptor names before the container process | ||||
| 	// can potentially move them (e.g., via dup2()).  If we don't do this now, | ||||
| 	// we won't know at checkpoint time which file descriptor to look up. | ||||
| 	fds, err := getPipeFds(childPid) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("error getting pipe fds for pid %d: %w", childPid, err) | ||||
| 	} | ||||
| 	p.setExternalDescriptors(fds) | ||||
|  | ||||
| 	// Wait for our first child to exit | ||||
| 	if err := p.waitForChildExit(childPid); err != nil { | ||||
| 		return fmt.Errorf("error waiting for our first child to exit: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	if err := p.createNetworkInterfaces(); err != nil { | ||||
| 		return fmt.Errorf("error creating network interfaces: %w", err) | ||||
| 	} | ||||
| 	if err := p.updateSpecState(); err != nil { | ||||
| 		return fmt.Errorf("error updating spec state: %w", err) | ||||
| 	} | ||||
| 	if err := p.sendConfig(); err != nil { | ||||
| 		return fmt.Errorf("error sending config to init process: %w", err) | ||||
| 	} | ||||
| 	var ( | ||||
| 		sentRun    bool | ||||
| 		sentResume bool | ||||
| 	) | ||||
|  | ||||
| 	ierr := parseSync(p.messageSockPair.parent, func(sync *syncT) error { | ||||
| 		switch sync.Type { | ||||
| 		case procSeccomp: | ||||
| 			if p.config.Config.Seccomp.ListenerPath == "" { | ||||
| 				return errors.New("listenerPath is not set") | ||||
| 			} | ||||
|  | ||||
| 			seccompFd, err := recvSeccompFd(uintptr(childPid), uintptr(sync.Fd)) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			defer unix.Close(seccompFd) | ||||
|  | ||||
| 			s, err := p.container.currentOCIState() | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
|  | ||||
| 			// initProcessStartTime hasn't been set yet. | ||||
| 			s.Pid = p.cmd.Process.Pid | ||||
| 			s.Status = specs.StateCreating | ||||
| 			containerProcessState := &specs.ContainerProcessState{ | ||||
| 				Version:  specs.Version, | ||||
| 				Fds:      []string{specs.SeccompFdName}, | ||||
| 				Pid:      s.Pid, | ||||
| 				Metadata: p.config.Config.Seccomp.ListenerMetadata, | ||||
| 				State:    *s, | ||||
| 			} | ||||
| 			if err := sendContainerProcessState(p.config.Config.Seccomp.ListenerPath, | ||||
| 				containerProcessState, seccompFd); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
|  | ||||
| 			// Sync with child. | ||||
| 			if err := writeSync(p.messageSockPair.parent, procSeccompDone); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		case procReady: | ||||
| 			// Set rlimits, this has to be done here because we lose permissions | ||||
| 			// to raise the limits once we enter a user-namespace | ||||
| 			if err := setupRlimits(p.config.Rlimits, p.pid()); err != nil { | ||||
| 				return fmt.Errorf("error setting rlimits for ready process: %w", err) | ||||
| 			} | ||||
| 			// call prestart and CreateRuntime hooks | ||||
| 			if !p.config.Config.Namespaces.Contains(configs.NEWNS) { | ||||
| 				// Setup cgroup before the hook, so that the prestart and CreateRuntime hook could apply cgroup permissions. | ||||
| 				if err := p.manager.Set(p.config.Config.Cgroups.Resources); err != nil { | ||||
| 					return fmt.Errorf("error setting cgroup config for ready process: %w", err) | ||||
| 				} | ||||
| 				if p.intelRdtManager != nil { | ||||
| 					if err := p.intelRdtManager.Set(p.config.Config); err != nil { | ||||
| 						return fmt.Errorf("error setting Intel RDT config for ready process: %w", err) | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				if len(p.config.Config.Hooks) != 0 { | ||||
| 					s, err := p.container.currentOCIState() | ||||
| 					if err != nil { | ||||
| 						return err | ||||
| 					} | ||||
| 					// initProcessStartTime hasn't been set yet. | ||||
| 					s.Pid = p.cmd.Process.Pid | ||||
| 					s.Status = specs.StateCreating | ||||
| 					hooks := p.config.Config.Hooks | ||||
|  | ||||
| 					if err := hooks[configs.Prestart].RunHooks(s); err != nil { | ||||
| 						return err | ||||
| 					} | ||||
| 					if err := hooks[configs.CreateRuntime].RunHooks(s); err != nil { | ||||
| 						return err | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// generate a timestamp indicating when the container was started | ||||
| 			p.container.created = time.Now().UTC() | ||||
| 			p.container.state = &createdState{ | ||||
| 				c: p.container, | ||||
| 			} | ||||
|  | ||||
| 			// NOTE: If the procRun state has been synced and the | ||||
| 			// runc-create process has been killed for some reason, | ||||
| 			// the runc-init[2:stage] process will be leaky. And | ||||
| 			// the runc command also fails to parse root directory | ||||
| 			// because the container doesn't have state.json. | ||||
| 			// | ||||
| 			// In order to cleanup the runc-init[2:stage] by | ||||
| 			// runc-delete/stop, we should store the status before | ||||
| 			// procRun sync. | ||||
| 			state, uerr := p.container.updateState(p) | ||||
| 			if uerr != nil { | ||||
| 				return fmt.Errorf("unable to store init state: %w", err) | ||||
| 			} | ||||
| 			p.container.initProcessStartTime = state.InitProcessStartTime | ||||
|  | ||||
| 			// Sync with child. | ||||
| 			if err := writeSync(p.messageSockPair.parent, procRun); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			sentRun = true | ||||
| 		case procHooks: | ||||
| 			// Setup cgroup before prestart hook, so that the prestart hook could apply cgroup permissions. | ||||
| 			if err := p.manager.Set(p.config.Config.Cgroups.Resources); err != nil { | ||||
| 				return fmt.Errorf("error setting cgroup config for procHooks process: %w", err) | ||||
| 			} | ||||
| 			if p.intelRdtManager != nil { | ||||
| 				if err := p.intelRdtManager.Set(p.config.Config); err != nil { | ||||
| 					return fmt.Errorf("error setting Intel RDT config for procHooks process: %w", err) | ||||
| 				} | ||||
| 			} | ||||
| 			if len(p.config.Config.Hooks) != 0 { | ||||
| 				s, err := p.container.currentOCIState() | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				// initProcessStartTime hasn't been set yet. | ||||
| 				s.Pid = p.cmd.Process.Pid | ||||
| 				s.Status = specs.StateCreating | ||||
| 				hooks := p.config.Config.Hooks | ||||
|  | ||||
| 				if err := hooks[configs.Prestart].RunHooks(s); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				if err := hooks[configs.CreateRuntime].RunHooks(s); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 			} | ||||
| 			// Sync with child. | ||||
| 			if err := writeSync(p.messageSockPair.parent, procResume); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			sentResume = true | ||||
| 		default: | ||||
| 			return errors.New("invalid JSON payload from child") | ||||
| 		} | ||||
|  | ||||
| 		return nil | ||||
| 	}) | ||||
|  | ||||
| 	if !sentRun { | ||||
| 		return fmt.Errorf("error during container init: %w", ierr) | ||||
| 	} | ||||
| 	if p.config.Config.Namespaces.Contains(configs.NEWNS) && !sentResume { | ||||
| 		return errors.New("could not synchronise after executing prestart and CreateRuntime hooks with container process") | ||||
| 	} | ||||
| 	if err := unix.Shutdown(int(p.messageSockPair.parent.Fd()), unix.SHUT_WR); err != nil { | ||||
| 		return &os.PathError{Op: "shutdown", Path: "(init pipe)", Err: err} | ||||
| 	} | ||||
|  | ||||
| 	// Must be done after Shutdown so the child will exit and we can wait for it. | ||||
| 	if ierr != nil { | ||||
| 		_, _ = p.wait() | ||||
| 		return ierr | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *initProcess) wait() (*os.ProcessState, error) { | ||||
| 	err := p.cmd.Wait() | ||||
| 	// we should kill all processes in cgroup when init is died if we use host PID namespace | ||||
| 	if p.sharePidns { | ||||
| 		_ = signalAllProcesses(p.manager, unix.SIGKILL) | ||||
| 	} | ||||
| 	return p.cmd.ProcessState, err | ||||
| } | ||||
|  | ||||
| func (p *initProcess) terminate() error { | ||||
| 	if p.cmd.Process == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	err := p.cmd.Process.Kill() | ||||
| 	if _, werr := p.wait(); err == nil { | ||||
| 		err = werr | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func (p *initProcess) startTime() (uint64, error) { | ||||
| 	stat, err := system.Stat(p.pid()) | ||||
| 	return stat.StartTime, err | ||||
| } | ||||
|  | ||||
| func (p *initProcess) updateSpecState() error { | ||||
| 	s, err := p.container.currentOCIState() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	p.config.SpecState = s | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *initProcess) sendConfig() error { | ||||
| 	// send the config to the container's init process, we don't use JSON Encode | ||||
| 	// here because there might be a problem in JSON decoder in some cases, see: | ||||
| 	// https://github.com/docker/docker/issues/14203#issuecomment-174177790 | ||||
| 	return utils.WriteJSON(p.messageSockPair.parent, p.config) | ||||
| } | ||||
|  | ||||
| func (p *initProcess) createNetworkInterfaces() error { | ||||
| 	for _, config := range p.config.Config.Networks { | ||||
| 		strategy, err := getStrategy(config.Type) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		n := &network{ | ||||
| 			Network: *config, | ||||
| 		} | ||||
| 		if err := strategy.create(n, p.pid()); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		p.config.Networks = append(p.config.Networks, n) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *initProcess) signal(sig os.Signal) error { | ||||
| 	s, ok := sig.(unix.Signal) | ||||
| 	if !ok { | ||||
| 		return errors.New("os: unsupported signal type") | ||||
| 	} | ||||
| 	return unix.Kill(p.pid(), s) | ||||
| } | ||||
|  | ||||
| func (p *initProcess) setExternalDescriptors(newFds []string) { | ||||
| 	p.fds = newFds | ||||
| } | ||||
|  | ||||
| func (p *initProcess) forwardChildLogs() chan error { | ||||
| 	return logs.ForwardLogs(p.logFilePair.parent) | ||||
| } | ||||
|  | ||||
| func recvSeccompFd(childPid, childFd uintptr) (int, error) { | ||||
| 	pidfd, _, errno := unix.Syscall(unix.SYS_PIDFD_OPEN, childPid, 0, 0) | ||||
| 	if errno != 0 { | ||||
| 		return -1, fmt.Errorf("performing SYS_PIDFD_OPEN syscall: %w", errno) | ||||
| 	} | ||||
| 	defer unix.Close(int(pidfd)) | ||||
|  | ||||
| 	seccompFd, _, errno := unix.Syscall(unix.SYS_PIDFD_GETFD, pidfd, childFd, 0) | ||||
| 	if errno != 0 { | ||||
| 		return -1, fmt.Errorf("performing SYS_PIDFD_GETFD syscall: %w", errno) | ||||
| 	} | ||||
|  | ||||
| 	return int(seccompFd), nil | ||||
| } | ||||
|  | ||||
| func sendContainerProcessState(listenerPath string, state *specs.ContainerProcessState, fd int) error { | ||||
| 	conn, err := net.Dial("unix", listenerPath) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to connect with seccomp agent specified in the seccomp profile: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	socket, err := conn.(*net.UnixConn).File() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("cannot get seccomp socket: %w", err) | ||||
| 	} | ||||
| 	defer socket.Close() | ||||
|  | ||||
| 	b, err := json.Marshal(state) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("cannot marshall seccomp state: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	err = utils.SendFds(socket, b, fd) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("cannot send seccomp fd to %s: %w", listenerPath, err) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func getPipeFds(pid int) ([]string, error) { | ||||
| 	fds := make([]string, 3) | ||||
|  | ||||
| 	dirPath := filepath.Join("/proc", strconv.Itoa(pid), "/fd") | ||||
| 	for i := 0; i < 3; i++ { | ||||
| 		// XXX: This breaks if the path is not a valid symlink (which can | ||||
| 		//      happen in certain particularly unlucky mount namespace setups). | ||||
| 		f := filepath.Join(dirPath, strconv.Itoa(i)) | ||||
| 		target, err := os.Readlink(f) | ||||
| 		if err != nil { | ||||
| 			// Ignore permission errors, for rootless containers and other | ||||
| 			// non-dumpable processes. if we can't get the fd for a particular | ||||
| 			// file, there's not much we can do. | ||||
| 			if os.IsPermission(err) { | ||||
| 				continue | ||||
| 			} | ||||
| 			return fds, err | ||||
| 		} | ||||
| 		fds[i] = target | ||||
| 	} | ||||
| 	return fds, nil | ||||
| } | ||||
|  | ||||
| // InitializeIO creates pipes for use with the process's stdio and returns the | ||||
| // opposite side for each. Do not use this if you want to have a pseudoterminal | ||||
| // set up for you by libcontainer (TODO: fix that too). | ||||
| // TODO: This is mostly unnecessary, and should be handled by clients. | ||||
| func (p *Process) InitializeIO(rootuid, rootgid int) (i *IO, err error) { | ||||
| 	var fds []uintptr | ||||
| 	i = &IO{} | ||||
| 	// cleanup in case of an error | ||||
| 	defer func() { | ||||
| 		if err != nil { | ||||
| 			for _, fd := range fds { | ||||
| 				_ = unix.Close(int(fd)) | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
| 	// STDIN | ||||
| 	r, w, err := os.Pipe() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	fds = append(fds, r.Fd(), w.Fd()) | ||||
| 	p.Stdin, i.Stdin = r, w | ||||
| 	// STDOUT | ||||
| 	if r, w, err = os.Pipe(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	fds = append(fds, r.Fd(), w.Fd()) | ||||
| 	p.Stdout, i.Stdout = w, r | ||||
| 	// STDERR | ||||
| 	if r, w, err = os.Pipe(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	fds = append(fds, r.Fd(), w.Fd()) | ||||
| 	p.Stderr, i.Stderr = w, r | ||||
| 	// change ownership of the pipes in case we are in a user namespace | ||||
| 	for _, fd := range fds { | ||||
| 		if err := unix.Fchown(int(fd), rootuid, rootgid); err != nil { | ||||
| 			return nil, &os.PathError{Op: "fchown", Path: "fd " + strconv.Itoa(int(fd)), Err: err} | ||||
| 		} | ||||
| 	} | ||||
| 	return i, nil | ||||
| } | ||||
|  | ||||
| // initWaiter returns a channel to wait on for making sure | ||||
| // runc init has finished the initial setup. | ||||
| func initWaiter(r io.Reader) chan error { | ||||
| 	ch := make(chan error, 1) | ||||
| 	go func() { | ||||
| 		defer close(ch) | ||||
|  | ||||
| 		inited := make([]byte, 1) | ||||
| 		n, err := r.Read(inited) | ||||
| 		if err == nil { | ||||
| 			if n < 1 { | ||||
| 				err = errors.New("short read") | ||||
| 			} else if inited[0] != 0 { | ||||
| 				err = fmt.Errorf("unexpected %d != 0", inited[0]) | ||||
| 			} else { | ||||
| 				ch <- nil | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 		ch <- fmt.Errorf("waiting for init preliminary setup: %w", err) | ||||
| 	}() | ||||
|  | ||||
| 	return ch | ||||
| } | ||||
							
								
								
									
										128
									
								
								vendor/github.com/opencontainers/runc/libcontainer/restored_process.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										128
									
								
								vendor/github.com/opencontainers/runc/libcontainer/restored_process.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,128 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/system" | ||||
| ) | ||||
|  | ||||
| func newRestoredProcess(cmd *exec.Cmd, fds []string) (*restoredProcess, error) { | ||||
| 	var err error | ||||
| 	pid := cmd.Process.Pid | ||||
| 	stat, err := system.Stat(pid) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &restoredProcess{ | ||||
| 		cmd:              cmd, | ||||
| 		processStartTime: stat.StartTime, | ||||
| 		fds:              fds, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| type restoredProcess struct { | ||||
| 	cmd              *exec.Cmd | ||||
| 	processStartTime uint64 | ||||
| 	fds              []string | ||||
| } | ||||
|  | ||||
| func (p *restoredProcess) start() error { | ||||
| 	return errors.New("restored process cannot be started") | ||||
| } | ||||
|  | ||||
| func (p *restoredProcess) pid() int { | ||||
| 	return p.cmd.Process.Pid | ||||
| } | ||||
|  | ||||
| func (p *restoredProcess) terminate() error { | ||||
| 	err := p.cmd.Process.Kill() | ||||
| 	if _, werr := p.wait(); err == nil { | ||||
| 		err = werr | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func (p *restoredProcess) wait() (*os.ProcessState, error) { | ||||
| 	// TODO: how do we wait on the actual process? | ||||
| 	// maybe use --exec-cmd in criu | ||||
| 	err := p.cmd.Wait() | ||||
| 	if err != nil { | ||||
| 		var exitErr *exec.ExitError | ||||
| 		if !errors.As(err, &exitErr) { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	st := p.cmd.ProcessState | ||||
| 	return st, nil | ||||
| } | ||||
|  | ||||
| func (p *restoredProcess) startTime() (uint64, error) { | ||||
| 	return p.processStartTime, nil | ||||
| } | ||||
|  | ||||
| func (p *restoredProcess) signal(s os.Signal) error { | ||||
| 	return p.cmd.Process.Signal(s) | ||||
| } | ||||
|  | ||||
| func (p *restoredProcess) externalDescriptors() []string { | ||||
| 	return p.fds | ||||
| } | ||||
|  | ||||
| func (p *restoredProcess) setExternalDescriptors(newFds []string) { | ||||
| 	p.fds = newFds | ||||
| } | ||||
|  | ||||
| func (p *restoredProcess) forwardChildLogs() chan error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // nonChildProcess represents a process where the calling process is not | ||||
| // the parent process.  This process is created when a factory loads a container from | ||||
| // a persisted state. | ||||
| type nonChildProcess struct { | ||||
| 	processPid       int | ||||
| 	processStartTime uint64 | ||||
| 	fds              []string | ||||
| } | ||||
|  | ||||
| func (p *nonChildProcess) start() error { | ||||
| 	return errors.New("restored process cannot be started") | ||||
| } | ||||
|  | ||||
| func (p *nonChildProcess) pid() int { | ||||
| 	return p.processPid | ||||
| } | ||||
|  | ||||
| func (p *nonChildProcess) terminate() error { | ||||
| 	return errors.New("restored process cannot be terminated") | ||||
| } | ||||
|  | ||||
| func (p *nonChildProcess) wait() (*os.ProcessState, error) { | ||||
| 	return nil, errors.New("restored process cannot be waited on") | ||||
| } | ||||
|  | ||||
| func (p *nonChildProcess) startTime() (uint64, error) { | ||||
| 	return p.processStartTime, nil | ||||
| } | ||||
|  | ||||
| func (p *nonChildProcess) signal(s os.Signal) error { | ||||
| 	proc, err := os.FindProcess(p.processPid) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return proc.Signal(s) | ||||
| } | ||||
|  | ||||
| func (p *nonChildProcess) externalDescriptors() []string { | ||||
| 	return p.fds | ||||
| } | ||||
|  | ||||
| func (p *nonChildProcess) setExternalDescriptors(newFds []string) { | ||||
| 	p.fds = newFds | ||||
| } | ||||
|  | ||||
| func (p *nonChildProcess) forwardChildLogs() chan error { | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										1155
									
								
								vendor/github.com/opencontainers/runc/libcontainer/rootfs_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1155
									
								
								vendor/github.com/opencontainers/runc/libcontainer/rootfs_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										113
									
								
								vendor/github.com/opencontainers/runc/libcontainer/seccomp/config.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										113
									
								
								vendor/github.com/opencontainers/runc/libcontainer/seccomp/config.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,113 +0,0 @@ | ||||
| package seccomp | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"sort" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs" | ||||
| ) | ||||
|  | ||||
| var operators = map[string]configs.Operator{ | ||||
| 	"SCMP_CMP_NE":        configs.NotEqualTo, | ||||
| 	"SCMP_CMP_LT":        configs.LessThan, | ||||
| 	"SCMP_CMP_LE":        configs.LessThanOrEqualTo, | ||||
| 	"SCMP_CMP_EQ":        configs.EqualTo, | ||||
| 	"SCMP_CMP_GE":        configs.GreaterThanOrEqualTo, | ||||
| 	"SCMP_CMP_GT":        configs.GreaterThan, | ||||
| 	"SCMP_CMP_MASKED_EQ": configs.MaskEqualTo, | ||||
| } | ||||
|  | ||||
| // KnownOperators returns the list of the known operations. | ||||
| // Used by `runc features`. | ||||
| func KnownOperators() []string { | ||||
| 	var res []string | ||||
| 	for k := range operators { | ||||
| 		res = append(res, k) | ||||
| 	} | ||||
| 	sort.Strings(res) | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| var actions = map[string]configs.Action{ | ||||
| 	"SCMP_ACT_KILL":         configs.Kill, | ||||
| 	"SCMP_ACT_ERRNO":        configs.Errno, | ||||
| 	"SCMP_ACT_TRAP":         configs.Trap, | ||||
| 	"SCMP_ACT_ALLOW":        configs.Allow, | ||||
| 	"SCMP_ACT_TRACE":        configs.Trace, | ||||
| 	"SCMP_ACT_LOG":          configs.Log, | ||||
| 	"SCMP_ACT_NOTIFY":       configs.Notify, | ||||
| 	"SCMP_ACT_KILL_THREAD":  configs.KillThread, | ||||
| 	"SCMP_ACT_KILL_PROCESS": configs.KillProcess, | ||||
| } | ||||
|  | ||||
| // KnownActions returns the list of the known actions. | ||||
| // Used by `runc features`. | ||||
| func KnownActions() []string { | ||||
| 	var res []string | ||||
| 	for k := range actions { | ||||
| 		res = append(res, k) | ||||
| 	} | ||||
| 	sort.Strings(res) | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| var archs = map[string]string{ | ||||
| 	"SCMP_ARCH_X86":         "x86", | ||||
| 	"SCMP_ARCH_X86_64":      "amd64", | ||||
| 	"SCMP_ARCH_X32":         "x32", | ||||
| 	"SCMP_ARCH_ARM":         "arm", | ||||
| 	"SCMP_ARCH_AARCH64":     "arm64", | ||||
| 	"SCMP_ARCH_MIPS":        "mips", | ||||
| 	"SCMP_ARCH_MIPS64":      "mips64", | ||||
| 	"SCMP_ARCH_MIPS64N32":   "mips64n32", | ||||
| 	"SCMP_ARCH_MIPSEL":      "mipsel", | ||||
| 	"SCMP_ARCH_MIPSEL64":    "mipsel64", | ||||
| 	"SCMP_ARCH_MIPSEL64N32": "mipsel64n32", | ||||
| 	"SCMP_ARCH_PPC":         "ppc", | ||||
| 	"SCMP_ARCH_PPC64":       "ppc64", | ||||
| 	"SCMP_ARCH_PPC64LE":     "ppc64le", | ||||
| 	"SCMP_ARCH_RISCV64":     "riscv64", | ||||
| 	"SCMP_ARCH_S390":        "s390", | ||||
| 	"SCMP_ARCH_S390X":       "s390x", | ||||
| } | ||||
|  | ||||
| // KnownArchs returns the list of the known archs. | ||||
| // Used by `runc features`. | ||||
| func KnownArchs() []string { | ||||
| 	var res []string | ||||
| 	for k := range archs { | ||||
| 		res = append(res, k) | ||||
| 	} | ||||
| 	sort.Strings(res) | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| // ConvertStringToOperator converts a string into a Seccomp comparison operator. | ||||
| // Comparison operators use the names they are assigned by Libseccomp's header. | ||||
| // Attempting to convert a string that is not a valid operator results in an | ||||
| // error. | ||||
| func ConvertStringToOperator(in string) (configs.Operator, error) { | ||||
| 	if op, ok := operators[in]; ok { | ||||
| 		return op, nil | ||||
| 	} | ||||
| 	return 0, fmt.Errorf("string %s is not a valid operator for seccomp", in) | ||||
| } | ||||
|  | ||||
| // ConvertStringToAction converts a string into a Seccomp rule match action. | ||||
| // Actions use the names they are assigned in Libseccomp's header. | ||||
| // Attempting to convert a string that is not a valid action results in an | ||||
| // error. | ||||
| func ConvertStringToAction(in string) (configs.Action, error) { | ||||
| 	if act, ok := actions[in]; ok { | ||||
| 		return act, nil | ||||
| 	} | ||||
| 	return 0, fmt.Errorf("string %s is not a valid action for seccomp", in) | ||||
| } | ||||
|  | ||||
| // ConvertStringToArch converts a string into a Seccomp comparison arch. | ||||
| func ConvertStringToArch(in string) (string, error) { | ||||
| 	if arch, ok := archs[in]; ok { | ||||
| 		return arch, nil | ||||
| 	} | ||||
| 	return "", fmt.Errorf("string %s is not a valid arch for seccomp", in) | ||||
| } | ||||
							
								
								
									
										721
									
								
								vendor/github.com/opencontainers/runc/libcontainer/seccomp/patchbpf/enosys_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										721
									
								
								vendor/github.com/opencontainers/runc/libcontainer/seccomp/patchbpf/enosys_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,721 +0,0 @@ | ||||
| //go:build cgo && seccomp | ||||
| // +build cgo,seccomp | ||||
|  | ||||
| package patchbpf | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"runtime" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	libseccomp "github.com/seccomp/libseccomp-golang" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"golang.org/x/net/bpf" | ||||
| 	"golang.org/x/sys/unix" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs" | ||||
| 	"github.com/opencontainers/runc/libcontainer/utils" | ||||
| ) | ||||
|  | ||||
| // #cgo pkg-config: libseccomp | ||||
| /* | ||||
| #include <errno.h> | ||||
| #include <stdint.h> | ||||
| #include <seccomp.h> | ||||
| #include <linux/seccomp.h> | ||||
|  | ||||
| const uint32_t C_ACT_ERRNO_ENOSYS = SCMP_ACT_ERRNO(ENOSYS); | ||||
|  | ||||
| // Copied from <linux/seccomp.h>. | ||||
|  | ||||
| #ifndef SECCOMP_SET_MODE_FILTER | ||||
| #	define SECCOMP_SET_MODE_FILTER 1 | ||||
| #endif | ||||
| const uintptr_t C_SET_MODE_FILTER = SECCOMP_SET_MODE_FILTER; | ||||
|  | ||||
| #ifndef SECCOMP_FILTER_FLAG_LOG | ||||
| #	define SECCOMP_FILTER_FLAG_LOG (1UL << 1) | ||||
| #endif | ||||
| const uintptr_t C_FILTER_FLAG_LOG = SECCOMP_FILTER_FLAG_LOG; | ||||
|  | ||||
| #ifndef SECCOMP_FILTER_FLAG_NEW_LISTENER | ||||
| #	define SECCOMP_FILTER_FLAG_NEW_LISTENER (1UL << 3) | ||||
| #endif | ||||
| const uintptr_t C_FILTER_FLAG_NEW_LISTENER = SECCOMP_FILTER_FLAG_NEW_LISTENER; | ||||
|  | ||||
| #ifndef AUDIT_ARCH_RISCV64 | ||||
| #ifndef EM_RISCV | ||||
| #define EM_RISCV		243 | ||||
| #endif | ||||
| #define AUDIT_ARCH_RISCV64	(EM_RISCV|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) | ||||
| #endif | ||||
|  | ||||
| // We use the AUDIT_ARCH_* values because those are the ones used by the kernel | ||||
| // and SCMP_ARCH_* sometimes has fake values (such as SCMP_ARCH_X32). But we | ||||
| // use <seccomp.h> so we get libseccomp's fallback definitions of AUDIT_ARCH_*. | ||||
|  | ||||
| const uint32_t C_AUDIT_ARCH_I386         = AUDIT_ARCH_I386; | ||||
| const uint32_t C_AUDIT_ARCH_X86_64       = AUDIT_ARCH_X86_64; | ||||
| const uint32_t C_AUDIT_ARCH_ARM          = AUDIT_ARCH_ARM; | ||||
| const uint32_t C_AUDIT_ARCH_AARCH64      = AUDIT_ARCH_AARCH64; | ||||
| const uint32_t C_AUDIT_ARCH_MIPS         = AUDIT_ARCH_MIPS; | ||||
| const uint32_t C_AUDIT_ARCH_MIPS64       = AUDIT_ARCH_MIPS64; | ||||
| const uint32_t C_AUDIT_ARCH_MIPS64N32    = AUDIT_ARCH_MIPS64N32; | ||||
| const uint32_t C_AUDIT_ARCH_MIPSEL       = AUDIT_ARCH_MIPSEL; | ||||
| const uint32_t C_AUDIT_ARCH_MIPSEL64     = AUDIT_ARCH_MIPSEL64; | ||||
| const uint32_t C_AUDIT_ARCH_MIPSEL64N32  = AUDIT_ARCH_MIPSEL64N32; | ||||
| const uint32_t C_AUDIT_ARCH_PPC          = AUDIT_ARCH_PPC; | ||||
| const uint32_t C_AUDIT_ARCH_PPC64        = AUDIT_ARCH_PPC64; | ||||
| const uint32_t C_AUDIT_ARCH_PPC64LE      = AUDIT_ARCH_PPC64LE; | ||||
| const uint32_t C_AUDIT_ARCH_S390         = AUDIT_ARCH_S390; | ||||
| const uint32_t C_AUDIT_ARCH_S390X        = AUDIT_ARCH_S390X; | ||||
| const uint32_t C_AUDIT_ARCH_RISCV64      = AUDIT_ARCH_RISCV64; | ||||
| */ | ||||
| import "C" | ||||
|  | ||||
| var retErrnoEnosys = uint32(C.C_ACT_ERRNO_ENOSYS) | ||||
|  | ||||
| // This syscall is used for multiplexing "large" syscalls on s390(x). Unknown | ||||
| // syscalls will end up with this syscall number, so we need to explicitly | ||||
| // return -ENOSYS for this syscall on those architectures. | ||||
| const s390xMultiplexSyscall libseccomp.ScmpSyscall = 0 | ||||
|  | ||||
| func isAllowAction(action configs.Action) bool { | ||||
| 	switch action { | ||||
| 	// Trace is considered an "allow" action because a good tracer should | ||||
| 	// support future syscalls (by handling -ENOSYS on its own), and giving | ||||
| 	// -ENOSYS will be disruptive for emulation. | ||||
| 	case configs.Allow, configs.Log, configs.Trace: | ||||
| 		return true | ||||
| 	default: | ||||
| 		return false | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func parseProgram(rdr io.Reader) ([]bpf.RawInstruction, error) { | ||||
| 	var program []bpf.RawInstruction | ||||
| loop: | ||||
| 	for { | ||||
| 		// Read the next instruction. We have to use NativeEndian because | ||||
| 		// seccomp_export_bpf outputs the program in *host* endian-ness. | ||||
| 		var insn unix.SockFilter | ||||
| 		if err := binary.Read(rdr, utils.NativeEndian, &insn); err != nil { | ||||
| 			if errors.Is(err, io.EOF) { | ||||
| 				// Parsing complete. | ||||
| 				break loop | ||||
| 			} | ||||
| 			if errors.Is(err, io.ErrUnexpectedEOF) { | ||||
| 				// Parsing stopped mid-instruction. | ||||
| 				return nil, fmt.Errorf("program parsing halted mid-instruction: %w", err) | ||||
| 			} | ||||
| 			// All other errors. | ||||
| 			return nil, fmt.Errorf("error parsing instructions: %w", err) | ||||
| 		} | ||||
| 		program = append(program, bpf.RawInstruction{ | ||||
| 			Op: insn.Code, | ||||
| 			Jt: insn.Jt, | ||||
| 			Jf: insn.Jf, | ||||
| 			K:  insn.K, | ||||
| 		}) | ||||
| 	} | ||||
| 	return program, nil | ||||
| } | ||||
|  | ||||
| func disassembleFilter(filter *libseccomp.ScmpFilter) ([]bpf.Instruction, error) { | ||||
| 	rdr, wtr, err := os.Pipe() | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("error creating scratch pipe: %w", err) | ||||
| 	} | ||||
| 	defer wtr.Close() | ||||
| 	defer rdr.Close() | ||||
|  | ||||
| 	readerBuffer := new(bytes.Buffer) | ||||
| 	errChan := make(chan error, 1) | ||||
| 	go func() { | ||||
| 		_, err := io.Copy(readerBuffer, rdr) | ||||
| 		errChan <- err | ||||
| 		close(errChan) | ||||
| 	}() | ||||
|  | ||||
| 	if err := filter.ExportBPF(wtr); err != nil { | ||||
| 		return nil, fmt.Errorf("error exporting BPF: %w", err) | ||||
| 	} | ||||
| 	// Close so that the reader actually gets EOF. | ||||
| 	_ = wtr.Close() | ||||
|  | ||||
| 	if copyErr := <-errChan; copyErr != nil { | ||||
| 		return nil, fmt.Errorf("error reading from ExportBPF pipe: %w", copyErr) | ||||
| 	} | ||||
|  | ||||
| 	// Parse the instructions. | ||||
| 	rawProgram, err := parseProgram(readerBuffer) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("parsing generated BPF filter: %w", err) | ||||
| 	} | ||||
| 	program, ok := bpf.Disassemble(rawProgram) | ||||
| 	if !ok { | ||||
| 		return nil, errors.New("could not disassemble entire BPF filter") | ||||
| 	} | ||||
| 	return program, nil | ||||
| } | ||||
|  | ||||
| type linuxAuditArch uint32 | ||||
|  | ||||
| const invalidArch linuxAuditArch = 0 | ||||
|  | ||||
| func scmpArchToAuditArch(arch libseccomp.ScmpArch) (linuxAuditArch, error) { | ||||
| 	switch arch { | ||||
| 	case libseccomp.ArchNative: | ||||
| 		// Convert to actual native architecture. | ||||
| 		arch, err := libseccomp.GetNativeArch() | ||||
| 		if err != nil { | ||||
| 			return invalidArch, fmt.Errorf("unable to get native arch: %w", err) | ||||
| 		} | ||||
| 		return scmpArchToAuditArch(arch) | ||||
| 	case libseccomp.ArchX86: | ||||
| 		return linuxAuditArch(C.C_AUDIT_ARCH_I386), nil | ||||
| 	case libseccomp.ArchAMD64, libseccomp.ArchX32: | ||||
| 		// NOTE: x32 is treated like x86_64 except all x32 syscalls have the | ||||
| 		//       30th bit of the syscall number set to indicate that it's not a | ||||
| 		//       normal x86_64 syscall. | ||||
| 		return linuxAuditArch(C.C_AUDIT_ARCH_X86_64), nil | ||||
| 	case libseccomp.ArchARM: | ||||
| 		return linuxAuditArch(C.C_AUDIT_ARCH_ARM), nil | ||||
| 	case libseccomp.ArchARM64: | ||||
| 		return linuxAuditArch(C.C_AUDIT_ARCH_AARCH64), nil | ||||
| 	case libseccomp.ArchMIPS: | ||||
| 		return linuxAuditArch(C.C_AUDIT_ARCH_MIPS), nil | ||||
| 	case libseccomp.ArchMIPS64: | ||||
| 		return linuxAuditArch(C.C_AUDIT_ARCH_MIPS64), nil | ||||
| 	case libseccomp.ArchMIPS64N32: | ||||
| 		return linuxAuditArch(C.C_AUDIT_ARCH_MIPS64N32), nil | ||||
| 	case libseccomp.ArchMIPSEL: | ||||
| 		return linuxAuditArch(C.C_AUDIT_ARCH_MIPSEL), nil | ||||
| 	case libseccomp.ArchMIPSEL64: | ||||
| 		return linuxAuditArch(C.C_AUDIT_ARCH_MIPSEL64), nil | ||||
| 	case libseccomp.ArchMIPSEL64N32: | ||||
| 		return linuxAuditArch(C.C_AUDIT_ARCH_MIPSEL64N32), nil | ||||
| 	case libseccomp.ArchPPC: | ||||
| 		return linuxAuditArch(C.C_AUDIT_ARCH_PPC), nil | ||||
| 	case libseccomp.ArchPPC64: | ||||
| 		return linuxAuditArch(C.C_AUDIT_ARCH_PPC64), nil | ||||
| 	case libseccomp.ArchPPC64LE: | ||||
| 		return linuxAuditArch(C.C_AUDIT_ARCH_PPC64LE), nil | ||||
| 	case libseccomp.ArchS390: | ||||
| 		return linuxAuditArch(C.C_AUDIT_ARCH_S390), nil | ||||
| 	case libseccomp.ArchS390X: | ||||
| 		return linuxAuditArch(C.C_AUDIT_ARCH_S390X), nil | ||||
| 	case libseccomp.ArchRISCV64: | ||||
| 		return linuxAuditArch(C.C_AUDIT_ARCH_RISCV64), nil | ||||
| 	default: | ||||
| 		return invalidArch, fmt.Errorf("unknown architecture: %v", arch) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type lastSyscallMap map[linuxAuditArch]map[libseccomp.ScmpArch]libseccomp.ScmpSyscall | ||||
|  | ||||
| // Figure out largest syscall number referenced in the filter for each | ||||
| // architecture. We will be generating code based on the native architecture | ||||
| // representation, but SCMP_ARCH_X32 means we have to track cases where the | ||||
| // same architecture has different largest syscalls based on the mode. | ||||
| func findLastSyscalls(config *configs.Seccomp) (lastSyscallMap, error) { | ||||
| 	scmpArchs := make(map[libseccomp.ScmpArch]struct{}) | ||||
| 	for _, ociArch := range config.Architectures { | ||||
| 		arch, err := libseccomp.GetArchFromString(ociArch) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("unable to validate seccomp architecture: %w", err) | ||||
| 		} | ||||
| 		scmpArchs[arch] = struct{}{} | ||||
| 	} | ||||
| 	// On architectures like ppc64le, Docker inexplicably doesn't include the | ||||
| 	// native architecture in the architecture list which results in no | ||||
| 	// architectures being present in the list at all (rendering the ENOSYS | ||||
| 	// stub a no-op). So, always include the native architecture. | ||||
| 	if nativeScmpArch, err := libseccomp.GetNativeArch(); err != nil { | ||||
| 		return nil, fmt.Errorf("unable to get native arch: %w", err) | ||||
| 	} else if _, ok := scmpArchs[nativeScmpArch]; !ok { | ||||
| 		logrus.Debugf("seccomp: adding implied native architecture %v to config set", nativeScmpArch) | ||||
| 		scmpArchs[nativeScmpArch] = struct{}{} | ||||
| 	} | ||||
| 	logrus.Debugf("seccomp: configured architecture set: %s", scmpArchs) | ||||
|  | ||||
| 	// Only loop over architectures which are present in the filter. Any other | ||||
| 	// architectures will get the libseccomp bad architecture action anyway. | ||||
| 	lastSyscalls := make(lastSyscallMap) | ||||
| 	for arch := range scmpArchs { | ||||
| 		auditArch, err := scmpArchToAuditArch(arch) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("cannot map architecture %v to AUDIT_ARCH_ constant: %w", arch, err) | ||||
| 		} | ||||
|  | ||||
| 		if _, ok := lastSyscalls[auditArch]; !ok { | ||||
| 			lastSyscalls[auditArch] = map[libseccomp.ScmpArch]libseccomp.ScmpSyscall{} | ||||
| 		} | ||||
| 		if _, ok := lastSyscalls[auditArch][arch]; ok { | ||||
| 			// Because of ArchNative we may hit the same entry multiple times. | ||||
| 			// Just skip it if we've seen this (linuxAuditArch, ScmpArch) | ||||
| 			// combination before. | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		// Find the largest syscall in the filter for this architecture. | ||||
| 		var largestSyscall libseccomp.ScmpSyscall | ||||
| 		for _, rule := range config.Syscalls { | ||||
| 			sysno, err := libseccomp.GetSyscallFromNameByArch(rule.Name, arch) | ||||
| 			if err != nil { | ||||
| 				// Ignore unknown syscalls. | ||||
| 				continue | ||||
| 			} | ||||
| 			if sysno > largestSyscall { | ||||
| 				largestSyscall = sysno | ||||
| 			} | ||||
| 		} | ||||
| 		if largestSyscall != 0 { | ||||
| 			logrus.Debugf("seccomp: largest syscall number for arch %v is %v", arch, largestSyscall) | ||||
| 			lastSyscalls[auditArch][arch] = largestSyscall | ||||
| 		} else { | ||||
| 			logrus.Warnf("could not find any syscalls for arch %v", arch) | ||||
| 			delete(lastSyscalls[auditArch], arch) | ||||
| 		} | ||||
| 	} | ||||
| 	return lastSyscalls, nil | ||||
| } | ||||
|  | ||||
| // FIXME FIXME FIXME | ||||
| // | ||||
| // This solution is less than ideal. In the future it would be great to have | ||||
| // per-arch information about which syscalls were added in which kernel | ||||
| // versions so we can create far more accurate filter rules (handling holes in | ||||
| // the syscall table and determining -ENOSYS requirements based on kernel | ||||
| // minimum version alone. | ||||
| // | ||||
| // This implementation can in principle cause issues with syscalls like | ||||
| // close_range(2) which were added out-of-order in the syscall table between | ||||
| // kernel releases. | ||||
| func generateEnosysStub(lastSyscalls lastSyscallMap) ([]bpf.Instruction, error) { | ||||
| 	// A jump-table for each linuxAuditArch used to generate the initial | ||||
| 	// conditional jumps -- measured from the *END* of the program so they | ||||
| 	// remain valid after prepending to the tail. | ||||
| 	archJumpTable := map[linuxAuditArch]uint32{} | ||||
|  | ||||
| 	// Generate our own -ENOSYS rules for each architecture. They have to be | ||||
| 	// generated in reverse (prepended to the tail of the program) because the | ||||
| 	// JumpIf jumps need to be computed from the end of the program. | ||||
| 	programTail := []bpf.Instruction{ | ||||
| 		// Fall-through rules jump into the filter. | ||||
| 		bpf.Jump{Skip: 1}, | ||||
| 		// Rules which jump to here get -ENOSYS. | ||||
| 		bpf.RetConstant{Val: retErrnoEnosys}, | ||||
| 	} | ||||
|  | ||||
| 	// Generate the syscall -ENOSYS rules. | ||||
| 	for auditArch, maxSyscalls := range lastSyscalls { | ||||
| 		// The number of instructions from the tail of this section which need | ||||
| 		// to be jumped in order to reach the -ENOSYS return. If the section | ||||
| 		// does not jump, it will fall through to the actual filter. | ||||
| 		baseJumpEnosys := uint32(len(programTail) - 1) | ||||
| 		baseJumpFilter := baseJumpEnosys + 1 | ||||
|  | ||||
| 		// Add the load instruction for the syscall number -- we jump here | ||||
| 		// directly from the arch code so we need to do it here. Sadly we can't | ||||
| 		// share this code between architecture branches. | ||||
| 		section := []bpf.Instruction{ | ||||
| 			// load [0] (syscall number) | ||||
| 			bpf.LoadAbsolute{Off: 0, Size: 4}, // NOTE: We assume sizeof(int) == 4. | ||||
| 		} | ||||
|  | ||||
| 		switch len(maxSyscalls) { | ||||
| 		case 0: | ||||
| 			// No syscalls found for this arch -- skip it and move on. | ||||
| 			continue | ||||
| 		case 1: | ||||
| 			// Get the only syscall and scmpArch in the map. | ||||
| 			var ( | ||||
| 				scmpArch libseccomp.ScmpArch | ||||
| 				sysno    libseccomp.ScmpSyscall | ||||
| 			) | ||||
| 			for arch, no := range maxSyscalls { | ||||
| 				sysno = no | ||||
| 				scmpArch = arch | ||||
| 			} | ||||
|  | ||||
| 			switch scmpArch { | ||||
| 			// Return -ENOSYS for setup(2) on s390(x). This syscall is used for | ||||
| 			// multiplexing "large syscall number" syscalls, but if the syscall | ||||
| 			// number is not known to the kernel then the syscall number is | ||||
| 			// left unchanged (and because it is sysno=0, you'll end up with | ||||
| 			// EPERM for syscalls the kernel doesn't know about). | ||||
| 			// | ||||
| 			// The actual setup(2) syscall is never used by userspace anymore | ||||
| 			// (and hasn't existed for decades) outside of this multiplexing | ||||
| 			// scheme so returning -ENOSYS is fine. | ||||
| 			case libseccomp.ArchS390, libseccomp.ArchS390X: | ||||
| 				section = append(section, []bpf.Instruction{ | ||||
| 					// jne [setup=0],1 | ||||
| 					bpf.JumpIf{ | ||||
| 						Cond:     bpf.JumpNotEqual, | ||||
| 						Val:      uint32(s390xMultiplexSyscall), | ||||
| 						SkipTrue: 1, | ||||
| 					}, | ||||
| 					// ret [ENOSYS] | ||||
| 					bpf.RetConstant{Val: retErrnoEnosys}, | ||||
| 				}...) | ||||
| 			} | ||||
|  | ||||
| 			// The simplest case just boils down to a single jgt instruction, | ||||
| 			// with special handling if baseJumpEnosys is larger than 255 (and | ||||
| 			// thus a long jump is required). | ||||
| 			var sectionTail []bpf.Instruction | ||||
| 			if baseJumpEnosys+1 <= 255 { | ||||
| 				sectionTail = []bpf.Instruction{ | ||||
| 					// jgt [syscall],[baseJumpEnosys+1] | ||||
| 					bpf.JumpIf{ | ||||
| 						Cond:     bpf.JumpGreaterThan, | ||||
| 						Val:      uint32(sysno), | ||||
| 						SkipTrue: uint8(baseJumpEnosys + 1), | ||||
| 					}, | ||||
| 					// ja [baseJumpFilter] | ||||
| 					bpf.Jump{Skip: baseJumpFilter}, | ||||
| 				} | ||||
| 			} else { | ||||
| 				sectionTail = []bpf.Instruction{ | ||||
| 					// jle [syscall],1 | ||||
| 					bpf.JumpIf{Cond: bpf.JumpLessOrEqual, Val: uint32(sysno), SkipTrue: 1}, | ||||
| 					// ja [baseJumpEnosys+1] | ||||
| 					bpf.Jump{Skip: baseJumpEnosys + 1}, | ||||
| 					// ja [baseJumpFilter] | ||||
| 					bpf.Jump{Skip: baseJumpFilter}, | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// If we're on x86 we need to add a check for x32 and if we're in | ||||
| 			// the wrong mode we jump over the section. | ||||
| 			if uint32(auditArch) == uint32(C.C_AUDIT_ARCH_X86_64) { | ||||
| 				// Generate a prefix to check the mode. | ||||
| 				switch scmpArch { | ||||
| 				case libseccomp.ArchAMD64: | ||||
| 					sectionTail = append([]bpf.Instruction{ | ||||
| 						// jset (1<<30),[len(tail)-1] | ||||
| 						bpf.JumpIf{ | ||||
| 							Cond:     bpf.JumpBitsSet, | ||||
| 							Val:      1 << 30, | ||||
| 							SkipTrue: uint8(len(sectionTail) - 1), | ||||
| 						}, | ||||
| 					}, sectionTail...) | ||||
| 				case libseccomp.ArchX32: | ||||
| 					sectionTail = append([]bpf.Instruction{ | ||||
| 						// jset (1<<30),0,[len(tail)-1] | ||||
| 						bpf.JumpIf{ | ||||
| 							Cond:     bpf.JumpBitsNotSet, | ||||
| 							Val:      1 << 30, | ||||
| 							SkipTrue: uint8(len(sectionTail) - 1), | ||||
| 						}, | ||||
| 					}, sectionTail...) | ||||
| 				default: | ||||
| 					return nil, fmt.Errorf("unknown amd64 native architecture %#x", scmpArch) | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			section = append(section, sectionTail...) | ||||
| 		case 2: | ||||
| 			// x32 and x86_64 are a unique case, we can't handle any others. | ||||
| 			if uint32(auditArch) != uint32(C.C_AUDIT_ARCH_X86_64) { | ||||
| 				return nil, fmt.Errorf("unknown architecture overlap on native arch %#x", auditArch) | ||||
| 			} | ||||
|  | ||||
| 			x32sysno, ok := maxSyscalls[libseccomp.ArchX32] | ||||
| 			if !ok { | ||||
| 				return nil, fmt.Errorf("missing %v in overlapping x86_64 arch: %v", libseccomp.ArchX32, maxSyscalls) | ||||
| 			} | ||||
| 			x86sysno, ok := maxSyscalls[libseccomp.ArchAMD64] | ||||
| 			if !ok { | ||||
| 				return nil, fmt.Errorf("missing %v in overlapping x86_64 arch: %v", libseccomp.ArchAMD64, maxSyscalls) | ||||
| 			} | ||||
|  | ||||
| 			// The x32 ABI indicates that a syscall is being made by an x32 | ||||
| 			// process by setting the 30th bit of the syscall number, but we | ||||
| 			// need to do some special-casing depending on whether we need to | ||||
| 			// do long jumps. | ||||
| 			if baseJumpEnosys+2 <= 255 { | ||||
| 				// For the simple case we want to have something like: | ||||
| 				//   jset (1<<30),1 | ||||
| 				//   jgt [x86 syscall],[baseJumpEnosys+2],1 | ||||
| 				//   jgt [x32 syscall],[baseJumpEnosys+1] | ||||
| 				//   ja [baseJumpFilter] | ||||
| 				section = append(section, []bpf.Instruction{ | ||||
| 					// jset (1<<30),1 | ||||
| 					bpf.JumpIf{Cond: bpf.JumpBitsSet, Val: 1 << 30, SkipTrue: 1}, | ||||
| 					// jgt [x86 syscall],[baseJumpEnosys+1],1 | ||||
| 					bpf.JumpIf{ | ||||
| 						Cond:     bpf.JumpGreaterThan, | ||||
| 						Val:      uint32(x86sysno), | ||||
| 						SkipTrue: uint8(baseJumpEnosys + 2), SkipFalse: 1, | ||||
| 					}, | ||||
| 					// jgt [x32 syscall],[baseJumpEnosys] | ||||
| 					bpf.JumpIf{ | ||||
| 						Cond:     bpf.JumpGreaterThan, | ||||
| 						Val:      uint32(x32sysno), | ||||
| 						SkipTrue: uint8(baseJumpEnosys + 1), | ||||
| 					}, | ||||
| 					// ja [baseJumpFilter] | ||||
| 					bpf.Jump{Skip: baseJumpFilter}, | ||||
| 				}...) | ||||
| 			} else { | ||||
| 				// But if the [baseJumpEnosys+2] jump is larger than 255 we | ||||
| 				// need to do a long jump like so: | ||||
| 				//   jset (1<<30),1 | ||||
| 				//   jgt [x86 syscall],1,2 | ||||
| 				//   jle [x32 syscall],1 | ||||
| 				//   ja [baseJumpEnosys+1] | ||||
| 				//   ja [baseJumpFilter] | ||||
| 				section = append(section, []bpf.Instruction{ | ||||
| 					// jset (1<<30),1 | ||||
| 					bpf.JumpIf{Cond: bpf.JumpBitsSet, Val: 1 << 30, SkipTrue: 1}, | ||||
| 					// jgt [x86 syscall],1,2 | ||||
| 					bpf.JumpIf{ | ||||
| 						Cond:     bpf.JumpGreaterThan, | ||||
| 						Val:      uint32(x86sysno), | ||||
| 						SkipTrue: 1, SkipFalse: 2, | ||||
| 					}, | ||||
| 					// jle [x32 syscall],[baseJumpEnosys] | ||||
| 					bpf.JumpIf{ | ||||
| 						Cond:     bpf.JumpLessOrEqual, | ||||
| 						Val:      uint32(x32sysno), | ||||
| 						SkipTrue: 1, | ||||
| 					}, | ||||
| 					// ja [baseJumpEnosys+1] | ||||
| 					bpf.Jump{Skip: baseJumpEnosys + 1}, | ||||
| 					// ja [baseJumpFilter] | ||||
| 					bpf.Jump{Skip: baseJumpFilter}, | ||||
| 				}...) | ||||
| 			} | ||||
| 		default: | ||||
| 			return nil, fmt.Errorf("invalid number of architecture overlaps: %v", len(maxSyscalls)) | ||||
| 		} | ||||
|  | ||||
| 		// Prepend this section to the tail. | ||||
| 		programTail = append(section, programTail...) | ||||
|  | ||||
| 		// Update jump table. | ||||
| 		archJumpTable[auditArch] = uint32(len(programTail)) | ||||
| 	} | ||||
|  | ||||
| 	// Add a dummy "jump to filter" for any architecture we might miss below. | ||||
| 	// Such architectures will probably get the BadArch action of the filter | ||||
| 	// regardless. | ||||
| 	programTail = append([]bpf.Instruction{ | ||||
| 		// ja [end of stub and start of filter] | ||||
| 		bpf.Jump{Skip: uint32(len(programTail))}, | ||||
| 	}, programTail...) | ||||
|  | ||||
| 	// Generate the jump rules for each architecture. This has to be done in | ||||
| 	// reverse as well for the same reason as above. We add to programTail | ||||
| 	// directly because the jumps are impacted by each architecture rule we add | ||||
| 	// as well. | ||||
| 	// | ||||
| 	// TODO: Maybe we want to optimise to avoid long jumps here? So sort the | ||||
| 	//       architectures based on how large the jumps are going to be, or | ||||
| 	//       re-sort the candidate architectures each time to make sure that we | ||||
| 	//       pick the largest jump which is going to be smaller than 255. | ||||
| 	for auditArch := range lastSyscalls { | ||||
| 		// We jump forwards but the jump table is calculated from the *END*. | ||||
| 		jump := uint32(len(programTail)) - archJumpTable[auditArch] | ||||
|  | ||||
| 		// Same routine as above -- this is a basic jeq check, complicated | ||||
| 		// slightly if it turns out that we need to do a long jump. | ||||
| 		if jump <= 255 { | ||||
| 			programTail = append([]bpf.Instruction{ | ||||
| 				// jeq [arch],[jump] | ||||
| 				bpf.JumpIf{ | ||||
| 					Cond:     bpf.JumpEqual, | ||||
| 					Val:      uint32(auditArch), | ||||
| 					SkipTrue: uint8(jump), | ||||
| 				}, | ||||
| 			}, programTail...) | ||||
| 		} else { | ||||
| 			programTail = append([]bpf.Instruction{ | ||||
| 				// jne [arch],1 | ||||
| 				bpf.JumpIf{ | ||||
| 					Cond:     bpf.JumpNotEqual, | ||||
| 					Val:      uint32(auditArch), | ||||
| 					SkipTrue: 1, | ||||
| 				}, | ||||
| 				// ja [jump] | ||||
| 				bpf.Jump{Skip: jump}, | ||||
| 			}, programTail...) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Prepend the load instruction for the architecture. | ||||
| 	programTail = append([]bpf.Instruction{ | ||||
| 		// load [4] (architecture) | ||||
| 		bpf.LoadAbsolute{Off: 4, Size: 4}, // NOTE: We assume sizeof(int) == 4. | ||||
| 	}, programTail...) | ||||
|  | ||||
| 	// And that's all folks! | ||||
| 	return programTail, nil | ||||
| } | ||||
|  | ||||
| func assemble(program []bpf.Instruction) ([]unix.SockFilter, error) { | ||||
| 	rawProgram, err := bpf.Assemble(program) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("error assembling program: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// Convert to []unix.SockFilter for unix.SockFilter. | ||||
| 	var filter []unix.SockFilter | ||||
| 	for _, insn := range rawProgram { | ||||
| 		filter = append(filter, unix.SockFilter{ | ||||
| 			Code: insn.Op, | ||||
| 			Jt:   insn.Jt, | ||||
| 			Jf:   insn.Jf, | ||||
| 			K:    insn.K, | ||||
| 		}) | ||||
| 	} | ||||
| 	return filter, nil | ||||
| } | ||||
|  | ||||
| func generatePatch(config *configs.Seccomp) ([]bpf.Instruction, error) { | ||||
| 	// Patch the generated cBPF only when there is not a defaultErrnoRet set | ||||
| 	// and it is different from ENOSYS | ||||
| 	if config.DefaultErrnoRet != nil && *config.DefaultErrnoRet == uint(retErrnoEnosys) { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 	// We only add the stub if the default action is not permissive. | ||||
| 	if isAllowAction(config.DefaultAction) { | ||||
| 		logrus.Debugf("seccomp: skipping -ENOSYS stub filter generation") | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	lastSyscalls, err := findLastSyscalls(config) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("error finding last syscalls for -ENOSYS stub: %w", err) | ||||
| 	} | ||||
| 	stubProgram, err := generateEnosysStub(lastSyscalls) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("error generating -ENOSYS stub: %w", err) | ||||
| 	} | ||||
| 	return stubProgram, nil | ||||
| } | ||||
|  | ||||
| func enosysPatchFilter(config *configs.Seccomp, filter *libseccomp.ScmpFilter) ([]unix.SockFilter, error) { | ||||
| 	program, err := disassembleFilter(filter) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("error disassembling original filter: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	patch, err := generatePatch(config) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("error generating patch for filter: %w", err) | ||||
| 	} | ||||
| 	fullProgram := append(patch, program...) | ||||
|  | ||||
| 	logrus.Debugf("seccomp: prepending -ENOSYS stub filter to user filter...") | ||||
| 	for idx, insn := range patch { | ||||
| 		logrus.Debugf("  [%4.1d] %s", idx, insn) | ||||
| 	} | ||||
| 	logrus.Debugf("  [....] --- original filter ---") | ||||
|  | ||||
| 	fprog, err := assemble(fullProgram) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("error assembling modified filter: %w", err) | ||||
| 	} | ||||
| 	return fprog, nil | ||||
| } | ||||
|  | ||||
| func filterFlags(config *configs.Seccomp, filter *libseccomp.ScmpFilter) (flags uint, noNewPrivs bool, err error) { | ||||
| 	// Ignore the error since pre-2.4 libseccomp is treated as API level 0. | ||||
| 	apiLevel, _ := libseccomp.GetAPI() | ||||
|  | ||||
| 	noNewPrivs, err = filter.GetNoNewPrivsBit() | ||||
| 	if err != nil { | ||||
| 		return 0, false, fmt.Errorf("unable to fetch no_new_privs filter bit: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	if apiLevel >= 3 { | ||||
| 		if logBit, err := filter.GetLogBit(); err != nil { | ||||
| 			return 0, false, fmt.Errorf("unable to fetch SECCOMP_FILTER_FLAG_LOG bit: %w", err) | ||||
| 		} else if logBit { | ||||
| 			flags |= uint(C.C_FILTER_FLAG_LOG) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// TODO: Support seccomp flags not yet added to libseccomp-golang... | ||||
|  | ||||
| 	for _, call := range config.Syscalls { | ||||
| 		if call.Action == configs.Notify { | ||||
| 			flags |= uint(C.C_FILTER_FLAG_NEW_LISTENER) | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func sysSeccompSetFilter(flags uint, filter []unix.SockFilter) (fd int, err error) { | ||||
| 	fprog := unix.SockFprog{ | ||||
| 		Len:    uint16(len(filter)), | ||||
| 		Filter: &filter[0], | ||||
| 	} | ||||
| 	fd = -1 // only return a valid fd when C_FILTER_FLAG_NEW_LISTENER is set | ||||
| 	// If no seccomp flags were requested we can use the old-school prctl(2). | ||||
| 	if flags == 0 { | ||||
| 		err = unix.Prctl(unix.PR_SET_SECCOMP, | ||||
| 			unix.SECCOMP_MODE_FILTER, | ||||
| 			uintptr(unsafe.Pointer(&fprog)), 0, 0) | ||||
| 	} else { | ||||
| 		fdptr, _, errno := unix.RawSyscall(unix.SYS_SECCOMP, | ||||
| 			uintptr(C.C_SET_MODE_FILTER), | ||||
| 			uintptr(flags), uintptr(unsafe.Pointer(&fprog))) | ||||
| 		if errno != 0 { | ||||
| 			err = errno | ||||
| 		} | ||||
| 		if flags&uint(C.C_FILTER_FLAG_NEW_LISTENER) != 0 { | ||||
| 			fd = int(fdptr) | ||||
| 		} | ||||
| 	} | ||||
| 	runtime.KeepAlive(filter) | ||||
| 	runtime.KeepAlive(fprog) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // PatchAndLoad takes a seccomp configuration and a libseccomp filter which has | ||||
| // been pre-configured with the set of rules in the seccomp config. It then | ||||
| // patches said filter to handle -ENOSYS in a much nicer manner than the | ||||
| // default libseccomp default action behaviour, and loads the patched filter | ||||
| // into the kernel for the current process. | ||||
| func PatchAndLoad(config *configs.Seccomp, filter *libseccomp.ScmpFilter) (int, error) { | ||||
| 	// Generate a patched filter. | ||||
| 	fprog, err := enosysPatchFilter(config, filter) | ||||
| 	if err != nil { | ||||
| 		return -1, fmt.Errorf("error patching filter: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// Get the set of libseccomp flags set. | ||||
| 	seccompFlags, noNewPrivs, err := filterFlags(config, filter) | ||||
| 	if err != nil { | ||||
| 		return -1, fmt.Errorf("unable to fetch seccomp filter flags: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// Set no_new_privs if it was requested, though in runc we handle | ||||
| 	// no_new_privs separately so warn if we hit this path. | ||||
| 	if noNewPrivs { | ||||
| 		logrus.Warnf("potentially misconfigured filter -- setting no_new_privs in seccomp path") | ||||
| 		if err := unix.Prctl(unix.PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); err != nil { | ||||
| 			return -1, fmt.Errorf("error enabling no_new_privs bit: %w", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Finally, load the filter. | ||||
| 	fd, err := sysSeccompSetFilter(seccompFlags, fprog) | ||||
| 	if err != nil { | ||||
| 		return -1, fmt.Errorf("error loading seccomp filter: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return fd, nil | ||||
| } | ||||
| @@ -1,4 +0,0 @@ | ||||
| //go:build !linux || !cgo || !seccomp | ||||
| // +build !linux !cgo !seccomp | ||||
|  | ||||
| package patchbpf | ||||
							
								
								
									
										268
									
								
								vendor/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										268
									
								
								vendor/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,268 +0,0 @@ | ||||
| //go:build cgo && seccomp | ||||
| // +build cgo,seccomp | ||||
|  | ||||
| package seccomp | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
|  | ||||
| 	libseccomp "github.com/seccomp/libseccomp-golang" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"golang.org/x/sys/unix" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs" | ||||
| 	"github.com/opencontainers/runc/libcontainer/seccomp/patchbpf" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	actTrace = libseccomp.ActTrace.SetReturnCode(int16(unix.EPERM)) | ||||
| 	actErrno = libseccomp.ActErrno.SetReturnCode(int16(unix.EPERM)) | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	// Linux system calls can have at most 6 arguments | ||||
| 	syscallMaxArguments int = 6 | ||||
| ) | ||||
|  | ||||
| // InitSeccomp installs the seccomp filters to be used in the container as | ||||
| // specified in config. | ||||
| // Returns the seccomp file descriptor if any of the filters include a | ||||
| // SCMP_ACT_NOTIFY action, otherwise returns -1. | ||||
| func InitSeccomp(config *configs.Seccomp) (int, error) { | ||||
| 	if config == nil { | ||||
| 		return -1, errors.New("cannot initialize Seccomp - nil config passed") | ||||
| 	} | ||||
|  | ||||
| 	defaultAction, err := getAction(config.DefaultAction, config.DefaultErrnoRet) | ||||
| 	if err != nil { | ||||
| 		return -1, errors.New("error initializing seccomp - invalid default action") | ||||
| 	} | ||||
|  | ||||
| 	// Ignore the error since pre-2.4 libseccomp is treated as API level 0. | ||||
| 	apiLevel, _ := libseccomp.GetAPI() | ||||
| 	for _, call := range config.Syscalls { | ||||
| 		if call.Action == configs.Notify { | ||||
| 			if apiLevel < 6 { | ||||
| 				return -1, fmt.Errorf("seccomp notify unsupported: API level: got %d, want at least 6. Please try with libseccomp >= 2.5.0 and Linux >= 5.7", apiLevel) | ||||
| 			} | ||||
|  | ||||
| 			// We can't allow the write syscall to notify to the seccomp agent. | ||||
| 			// After InitSeccomp() is called, we need to syncParentSeccomp() to write the seccomp fd plain | ||||
| 			// number, so the parent sends it to the seccomp agent. If we use SCMP_ACT_NOTIFY on write, we | ||||
| 			// never can write the seccomp fd to the parent and therefore the seccomp agent never receives | ||||
| 			// the seccomp fd and runc is hang during initialization. | ||||
| 			// | ||||
| 			// Note that read()/close(), that are also used in syncParentSeccomp(), _can_ use SCMP_ACT_NOTIFY. | ||||
| 			// Because we write the seccomp fd on the pipe to the parent, the parent is able to proceed and | ||||
| 			// send the seccomp fd to the agent (it is another process and not subject to the seccomp | ||||
| 			// filter). We will be blocked on read()/close() inside syncParentSeccomp() but if the seccomp | ||||
| 			// agent allows those syscalls to proceed, initialization works just fine and the agent can | ||||
| 			// handle future read()/close() syscalls as it wanted. | ||||
| 			if call.Name == "write" { | ||||
| 				return -1, errors.New("SCMP_ACT_NOTIFY cannot be used for the write syscall") | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// See comment on why write is not allowed. The same reason applies, as this can mean handling write too. | ||||
| 	if defaultAction == libseccomp.ActNotify { | ||||
| 		return -1, errors.New("SCMP_ACT_NOTIFY cannot be used as default action") | ||||
| 	} | ||||
|  | ||||
| 	filter, err := libseccomp.NewFilter(defaultAction) | ||||
| 	if err != nil { | ||||
| 		return -1, fmt.Errorf("error creating filter: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// Add extra architectures | ||||
| 	for _, arch := range config.Architectures { | ||||
| 		scmpArch, err := libseccomp.GetArchFromString(arch) | ||||
| 		if err != nil { | ||||
| 			return -1, fmt.Errorf("error validating Seccomp architecture: %w", err) | ||||
| 		} | ||||
| 		if err := filter.AddArch(scmpArch); err != nil { | ||||
| 			return -1, fmt.Errorf("error adding architecture to seccomp filter: %w", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Unset no new privs bit | ||||
| 	if err := filter.SetNoNewPrivsBit(false); err != nil { | ||||
| 		return -1, fmt.Errorf("error setting no new privileges: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// Add a rule for each syscall | ||||
| 	for _, call := range config.Syscalls { | ||||
| 		if call == nil { | ||||
| 			return -1, errors.New("encountered nil syscall while initializing Seccomp") | ||||
| 		} | ||||
|  | ||||
| 		if err := matchCall(filter, call, defaultAction); err != nil { | ||||
| 			return -1, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	seccompFd, err := patchbpf.PatchAndLoad(config, filter) | ||||
| 	if err != nil { | ||||
| 		return -1, fmt.Errorf("error loading seccomp filter into kernel: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return seccompFd, nil | ||||
| } | ||||
|  | ||||
| // Convert Libcontainer Action to Libseccomp ScmpAction | ||||
| func getAction(act configs.Action, errnoRet *uint) (libseccomp.ScmpAction, error) { | ||||
| 	switch act { | ||||
| 	case configs.Kill, configs.KillThread: | ||||
| 		return libseccomp.ActKillThread, nil | ||||
| 	case configs.Errno: | ||||
| 		if errnoRet != nil { | ||||
| 			return libseccomp.ActErrno.SetReturnCode(int16(*errnoRet)), nil | ||||
| 		} | ||||
| 		return actErrno, nil | ||||
| 	case configs.Trap: | ||||
| 		return libseccomp.ActTrap, nil | ||||
| 	case configs.Allow: | ||||
| 		return libseccomp.ActAllow, nil | ||||
| 	case configs.Trace: | ||||
| 		if errnoRet != nil { | ||||
| 			return libseccomp.ActTrace.SetReturnCode(int16(*errnoRet)), nil | ||||
| 		} | ||||
| 		return actTrace, nil | ||||
| 	case configs.Log: | ||||
| 		return libseccomp.ActLog, nil | ||||
| 	case configs.Notify: | ||||
| 		return libseccomp.ActNotify, nil | ||||
| 	case configs.KillProcess: | ||||
| 		return libseccomp.ActKillProcess, nil | ||||
| 	default: | ||||
| 		return libseccomp.ActInvalid, errors.New("invalid action, cannot use in rule") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Convert Libcontainer Operator to Libseccomp ScmpCompareOp | ||||
| func getOperator(op configs.Operator) (libseccomp.ScmpCompareOp, error) { | ||||
| 	switch op { | ||||
| 	case configs.EqualTo: | ||||
| 		return libseccomp.CompareEqual, nil | ||||
| 	case configs.NotEqualTo: | ||||
| 		return libseccomp.CompareNotEqual, nil | ||||
| 	case configs.GreaterThan: | ||||
| 		return libseccomp.CompareGreater, nil | ||||
| 	case configs.GreaterThanOrEqualTo: | ||||
| 		return libseccomp.CompareGreaterEqual, nil | ||||
| 	case configs.LessThan: | ||||
| 		return libseccomp.CompareLess, nil | ||||
| 	case configs.LessThanOrEqualTo: | ||||
| 		return libseccomp.CompareLessOrEqual, nil | ||||
| 	case configs.MaskEqualTo: | ||||
| 		return libseccomp.CompareMaskedEqual, nil | ||||
| 	default: | ||||
| 		return libseccomp.CompareInvalid, errors.New("invalid operator, cannot use in rule") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Convert Libcontainer Arg to Libseccomp ScmpCondition | ||||
| func getCondition(arg *configs.Arg) (libseccomp.ScmpCondition, error) { | ||||
| 	cond := libseccomp.ScmpCondition{} | ||||
|  | ||||
| 	if arg == nil { | ||||
| 		return cond, errors.New("cannot convert nil to syscall condition") | ||||
| 	} | ||||
|  | ||||
| 	op, err := getOperator(arg.Op) | ||||
| 	if err != nil { | ||||
| 		return cond, err | ||||
| 	} | ||||
|  | ||||
| 	return libseccomp.MakeCondition(arg.Index, op, arg.Value, arg.ValueTwo) | ||||
| } | ||||
|  | ||||
| // Add a rule to match a single syscall | ||||
| func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall, defAct libseccomp.ScmpAction) error { | ||||
| 	if call == nil || filter == nil { | ||||
| 		return errors.New("cannot use nil as syscall to block") | ||||
| 	} | ||||
|  | ||||
| 	if len(call.Name) == 0 { | ||||
| 		return errors.New("empty string is not a valid syscall") | ||||
| 	} | ||||
|  | ||||
| 	// Convert the call's action to the libseccomp equivalent | ||||
| 	callAct, err := getAction(call.Action, call.ErrnoRet) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("action in seccomp profile is invalid: %w", err) | ||||
| 	} | ||||
| 	if callAct == defAct { | ||||
| 		// This rule is redundant, silently skip it | ||||
| 		// to avoid error from AddRule. | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	// If we can't resolve the syscall, assume it is not supported | ||||
| 	// by this kernel. Warn about it, don't error out. | ||||
| 	callNum, err := libseccomp.GetSyscallFromName(call.Name) | ||||
| 	if err != nil { | ||||
| 		logrus.Debugf("unknown seccomp syscall %q ignored", call.Name) | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	// Unconditional match - just add the rule | ||||
| 	if len(call.Args) == 0 { | ||||
| 		if err := filter.AddRule(callNum, callAct); err != nil { | ||||
| 			return fmt.Errorf("error adding seccomp filter rule for syscall %s: %w", call.Name, err) | ||||
| 		} | ||||
| 	} else { | ||||
| 		// If two or more arguments have the same condition, | ||||
| 		// Revert to old behavior, adding each condition as a separate rule | ||||
| 		argCounts := make([]uint, syscallMaxArguments) | ||||
| 		conditions := []libseccomp.ScmpCondition{} | ||||
|  | ||||
| 		for _, cond := range call.Args { | ||||
| 			newCond, err := getCondition(cond) | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("error creating seccomp syscall condition for syscall %s: %w", call.Name, err) | ||||
| 			} | ||||
|  | ||||
| 			argCounts[cond.Index] += 1 | ||||
|  | ||||
| 			conditions = append(conditions, newCond) | ||||
| 		} | ||||
|  | ||||
| 		hasMultipleArgs := false | ||||
| 		for _, count := range argCounts { | ||||
| 			if count > 1 { | ||||
| 				hasMultipleArgs = true | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if hasMultipleArgs { | ||||
| 			// Revert to old behavior | ||||
| 			// Add each condition attached to a separate rule | ||||
| 			for _, cond := range conditions { | ||||
| 				condArr := []libseccomp.ScmpCondition{cond} | ||||
|  | ||||
| 				if err := filter.AddRuleConditional(callNum, callAct, condArr); err != nil { | ||||
| 					return fmt.Errorf("error adding seccomp rule for syscall %s: %w", call.Name, err) | ||||
| 				} | ||||
| 			} | ||||
| 		} else { | ||||
| 			// No conditions share same argument | ||||
| 			// Use new, proper behavior | ||||
| 			if err := filter.AddRuleConditional(callNum, callAct, conditions); err != nil { | ||||
| 				return fmt.Errorf("error adding seccomp rule for syscall %s: %w", call.Name, err) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Version returns major, minor, and micro. | ||||
| func Version() (uint, uint, uint) { | ||||
| 	return libseccomp.GetLibraryVersion() | ||||
| } | ||||
|  | ||||
| // Enabled is true if seccomp support is compiled in. | ||||
| const Enabled = true | ||||
							
								
								
									
										28
									
								
								vendor/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_unsupported.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								vendor/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_unsupported.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,28 +0,0 @@ | ||||
| //go:build !linux || !cgo || !seccomp | ||||
| // +build !linux !cgo !seccomp | ||||
|  | ||||
| package seccomp | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs" | ||||
| ) | ||||
|  | ||||
| var ErrSeccompNotEnabled = errors.New("seccomp: config provided but seccomp not supported") | ||||
|  | ||||
| // InitSeccomp does nothing because seccomp is not supported. | ||||
| func InitSeccomp(config *configs.Seccomp) (int, error) { | ||||
| 	if config != nil { | ||||
| 		return -1, ErrSeccompNotEnabled | ||||
| 	} | ||||
| 	return -1, nil | ||||
| } | ||||
|  | ||||
| // Version returns major, minor, and micro. | ||||
| func Version() (uint, uint, uint) { | ||||
| 	return 0, 0, 0 | ||||
| } | ||||
|  | ||||
| // Enabled is true if seccomp support is compiled in. | ||||
| const Enabled = false | ||||
							
								
								
									
										149
									
								
								vendor/github.com/opencontainers/runc/libcontainer/setns_init_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										149
									
								
								vendor/github.com/opencontainers/runc/libcontainer/setns_init_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,149 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"strconv" | ||||
|  | ||||
| 	"github.com/opencontainers/selinux/go-selinux" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"golang.org/x/sys/unix" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/apparmor" | ||||
| 	"github.com/opencontainers/runc/libcontainer/keys" | ||||
| 	"github.com/opencontainers/runc/libcontainer/seccomp" | ||||
| 	"github.com/opencontainers/runc/libcontainer/system" | ||||
| 	"github.com/opencontainers/runc/libcontainer/utils" | ||||
| ) | ||||
|  | ||||
| // linuxSetnsInit performs the container's initialization for running a new process | ||||
| // inside an existing container. | ||||
| type linuxSetnsInit struct { | ||||
| 	pipe          *os.File | ||||
| 	consoleSocket *os.File | ||||
| 	config        *initConfig | ||||
| 	logFd         int | ||||
| } | ||||
|  | ||||
| func (l *linuxSetnsInit) getSessionRingName() string { | ||||
| 	return "_ses." + l.config.ContainerId | ||||
| } | ||||
|  | ||||
| func (l *linuxSetnsInit) Init() error { | ||||
| 	if !l.config.Config.NoNewKeyring { | ||||
| 		if err := selinux.SetKeyLabel(l.config.ProcessLabel); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		defer selinux.SetKeyLabel("") //nolint: errcheck | ||||
| 		// Do not inherit the parent's session keyring. | ||||
| 		if _, err := keys.JoinSessionKeyring(l.getSessionRingName()); err != nil { | ||||
| 			// Same justification as in standart_init_linux.go as to why we | ||||
| 			// don't bail on ENOSYS. | ||||
| 			// | ||||
| 			// TODO(cyphar): And we should have logging here too. | ||||
| 			if !errors.Is(err, unix.ENOSYS) { | ||||
| 				return fmt.Errorf("unable to join session keyring: %w", err) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if l.config.CreateConsole { | ||||
| 		if err := setupConsole(l.consoleSocket, l.config, false); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := system.Setctty(); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	if l.config.NoNewPrivileges { | ||||
| 		if err := unix.Prctl(unix.PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Tell our parent that we're ready to exec. This must be done before the | ||||
| 	// Seccomp rules have been applied, because we need to be able to read and | ||||
| 	// write to a socket. | ||||
| 	if err := syncParentReady(l.pipe); err != nil { | ||||
| 		return fmt.Errorf("sync ready: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	if err := selinux.SetExecLabel(l.config.ProcessLabel); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer selinux.SetExecLabel("") //nolint: errcheck | ||||
| 	// Without NoNewPrivileges seccomp is a privileged operation, so we need to | ||||
| 	// do this before dropping capabilities; otherwise do it as late as possible | ||||
| 	// just before execve so as few syscalls take place after it as possible. | ||||
| 	if l.config.Config.Seccomp != nil && !l.config.NoNewPrivileges { | ||||
| 		seccompFd, err := seccomp.InitSeccomp(l.config.Config.Seccomp) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		if err := syncParentSeccomp(l.pipe, seccompFd); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	if err := finalizeNamespace(l.config); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := apparmor.ApplyProfile(l.config.AppArmorProfile); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Check for the arg before waiting to make sure it exists and it is | ||||
| 	// returned as a create time error. | ||||
| 	name, err := exec.LookPath(l.config.Args[0]) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	// exec.LookPath in Go < 1.20 might return no error for an executable | ||||
| 	// residing on a file system mounted with noexec flag, so perform this | ||||
| 	// extra check now while we can still return a proper error. | ||||
| 	// TODO: remove this once go < 1.20 is not supported. | ||||
| 	if err := eaccess(name); err != nil { | ||||
| 		return &os.PathError{Op: "eaccess", Path: name, Err: err} | ||||
| 	} | ||||
|  | ||||
| 	// Set seccomp as close to execve as possible, so as few syscalls take | ||||
| 	// place afterward (reducing the amount of syscalls that users need to | ||||
| 	// enable in their seccomp profiles). | ||||
| 	if l.config.Config.Seccomp != nil && l.config.NoNewPrivileges { | ||||
| 		seccompFd, err := seccomp.InitSeccomp(l.config.Config.Seccomp) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("unable to init seccomp: %w", err) | ||||
| 		} | ||||
|  | ||||
| 		if err := syncParentSeccomp(l.pipe, seccompFd); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	logrus.Debugf("setns_init: about to exec") | ||||
| 	// Close the log pipe fd so the parent's ForwardLogs can exit. | ||||
| 	if err := unix.Close(l.logFd); err != nil { | ||||
| 		return &os.PathError{Op: "close log pipe", Path: "fd " + strconv.Itoa(l.logFd), Err: err} | ||||
| 	} | ||||
|  | ||||
| 	// Close all file descriptors we are not passing to the container. This is | ||||
| 	// necessary because the execve target could use internal runc fds as the | ||||
| 	// execve path, potentially giving access to binary files from the host | ||||
| 	// (which can then be opened by container processes, leading to container | ||||
| 	// escapes). Note that because this operation will close any open file | ||||
| 	// descriptors that are referenced by (*os.File) handles from underneath | ||||
| 	// the Go runtime, we must not do any file operations after this point | ||||
| 	// (otherwise the (*os.File) finaliser could close the wrong file). See | ||||
| 	// CVE-2024-21626 for more information as to why this protection is | ||||
| 	// necessary. | ||||
| 	// | ||||
| 	// This is not needed for runc-dmz, because the extra execve(2) step means | ||||
| 	// that all O_CLOEXEC file descriptors have already been closed and thus | ||||
| 	// the second execve(2) from runc-dmz cannot access internal file | ||||
| 	// descriptors from runc. | ||||
| 	if err := utils.UnsafeCloseFrom(l.config.PassedFilesCount + 3); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return system.Exec(name, l.config.Args[0:], os.Environ()) | ||||
| } | ||||
							
								
								
									
										282
									
								
								vendor/github.com/opencontainers/runc/libcontainer/standard_init_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										282
									
								
								vendor/github.com/opencontainers/runc/libcontainer/standard_init_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,282 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"strconv" | ||||
|  | ||||
| 	"github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	"github.com/opencontainers/selinux/go-selinux" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"golang.org/x/sys/unix" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/apparmor" | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs" | ||||
| 	"github.com/opencontainers/runc/libcontainer/keys" | ||||
| 	"github.com/opencontainers/runc/libcontainer/seccomp" | ||||
| 	"github.com/opencontainers/runc/libcontainer/system" | ||||
| 	"github.com/opencontainers/runc/libcontainer/utils" | ||||
| ) | ||||
|  | ||||
| type linuxStandardInit struct { | ||||
| 	pipe          *os.File | ||||
| 	consoleSocket *os.File | ||||
| 	parentPid     int | ||||
| 	fifoFd        int | ||||
| 	logFd         int | ||||
| 	mountFds      []int | ||||
| 	config        *initConfig | ||||
| } | ||||
|  | ||||
| func (l *linuxStandardInit) getSessionRingParams() (string, uint32, uint32) { | ||||
| 	var newperms uint32 | ||||
|  | ||||
| 	if l.config.Config.Namespaces.Contains(configs.NEWUSER) { | ||||
| 		// With user ns we need 'other' search permissions. | ||||
| 		newperms = 0x8 | ||||
| 	} else { | ||||
| 		// Without user ns we need 'UID' search permissions. | ||||
| 		newperms = 0x80000 | ||||
| 	} | ||||
|  | ||||
| 	// Create a unique per session container name that we can join in setns; | ||||
| 	// However, other containers can also join it. | ||||
| 	return "_ses." + l.config.ContainerId, 0xffffffff, newperms | ||||
| } | ||||
|  | ||||
| func (l *linuxStandardInit) Init() error { | ||||
| 	if !l.config.Config.NoNewKeyring { | ||||
| 		if err := selinux.SetKeyLabel(l.config.ProcessLabel); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		defer selinux.SetKeyLabel("") //nolint: errcheck | ||||
| 		ringname, keepperms, newperms := l.getSessionRingParams() | ||||
|  | ||||
| 		// Do not inherit the parent's session keyring. | ||||
| 		if sessKeyId, err := keys.JoinSessionKeyring(ringname); err != nil { | ||||
| 			// If keyrings aren't supported then it is likely we are on an | ||||
| 			// older kernel (or inside an LXC container). While we could bail, | ||||
| 			// the security feature we are using here is best-effort (it only | ||||
| 			// really provides marginal protection since VFS credentials are | ||||
| 			// the only significant protection of keyrings). | ||||
| 			// | ||||
| 			// TODO(cyphar): Log this so people know what's going on, once we | ||||
| 			//               have proper logging in 'runc init'. | ||||
| 			if !errors.Is(err, unix.ENOSYS) { | ||||
| 				return fmt.Errorf("unable to join session keyring: %w", err) | ||||
| 			} | ||||
| 		} else { | ||||
| 			// Make session keyring searchable. If we've gotten this far we | ||||
| 			// bail on any error -- we don't want to have a keyring with bad | ||||
| 			// permissions. | ||||
| 			if err := keys.ModKeyringPerm(sessKeyId, keepperms, newperms); err != nil { | ||||
| 				return fmt.Errorf("unable to mod keyring permissions: %w", err) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if err := setupNetwork(l.config); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := setupRoute(l.config.Config); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// initialises the labeling system | ||||
| 	selinux.GetEnabled() | ||||
|  | ||||
| 	// We don't need the mountFds after prepareRootfs() nor if it fails. | ||||
| 	err := prepareRootfs(l.pipe, l.config, l.mountFds) | ||||
| 	for _, m := range l.mountFds { | ||||
| 		if m == -1 { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if err := unix.Close(m); err != nil { | ||||
| 			return fmt.Errorf("Unable to close mountFds fds: %w", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Set up the console. This has to be done *before* we finalize the rootfs, | ||||
| 	// but *after* we've given the user the chance to set up all of the mounts | ||||
| 	// they wanted. | ||||
| 	if l.config.CreateConsole { | ||||
| 		if err := setupConsole(l.consoleSocket, l.config, true); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := system.Setctty(); err != nil { | ||||
| 			return &os.SyscallError{Syscall: "ioctl(setctty)", Err: err} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Finish the rootfs setup. | ||||
| 	if l.config.Config.Namespaces.Contains(configs.NEWNS) { | ||||
| 		if err := finalizeRootfs(l.config.Config); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if hostname := l.config.Config.Hostname; hostname != "" { | ||||
| 		if err := unix.Sethostname([]byte(hostname)); err != nil { | ||||
| 			return &os.SyscallError{Syscall: "sethostname", Err: err} | ||||
| 		} | ||||
| 	} | ||||
| 	if err := apparmor.ApplyProfile(l.config.AppArmorProfile); err != nil { | ||||
| 		return fmt.Errorf("unable to apply apparmor profile: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	for key, value := range l.config.Config.Sysctl { | ||||
| 		if err := writeSystemProperty(key, value); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	for _, path := range l.config.Config.ReadonlyPaths { | ||||
| 		if err := readonlyPath(path); err != nil { | ||||
| 			return fmt.Errorf("can't make %q read-only: %w", path, err) | ||||
| 		} | ||||
| 	} | ||||
| 	for _, path := range l.config.Config.MaskPaths { | ||||
| 		if err := maskPath(path, l.config.Config.MountLabel); err != nil { | ||||
| 			return fmt.Errorf("can't mask path %s: %w", path, err) | ||||
| 		} | ||||
| 	} | ||||
| 	pdeath, err := system.GetParentDeathSignal() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("can't get pdeath signal: %w", err) | ||||
| 	} | ||||
| 	if l.config.NoNewPrivileges { | ||||
| 		if err := unix.Prctl(unix.PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); err != nil { | ||||
| 			return &os.SyscallError{Syscall: "prctl(SET_NO_NEW_PRIVS)", Err: err} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Tell our parent that we're ready to exec. This must be done before the | ||||
| 	// Seccomp rules have been applied, because we need to be able to read and | ||||
| 	// write to a socket. | ||||
| 	if err := syncParentReady(l.pipe); err != nil { | ||||
| 		return fmt.Errorf("sync ready: %w", err) | ||||
| 	} | ||||
| 	if err := selinux.SetExecLabel(l.config.ProcessLabel); err != nil { | ||||
| 		return fmt.Errorf("can't set process label: %w", err) | ||||
| 	} | ||||
| 	defer selinux.SetExecLabel("") //nolint: errcheck | ||||
| 	// Without NoNewPrivileges seccomp is a privileged operation, so we need to | ||||
| 	// do this before dropping capabilities; otherwise do it as late as possible | ||||
| 	// just before execve so as few syscalls take place after it as possible. | ||||
| 	if l.config.Config.Seccomp != nil && !l.config.NoNewPrivileges { | ||||
| 		seccompFd, err := seccomp.InitSeccomp(l.config.Config.Seccomp) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		if err := syncParentSeccomp(l.pipe, seccompFd); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	if err := finalizeNamespace(l.config); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	// finalizeNamespace can change user/group which clears the parent death | ||||
| 	// signal, so we restore it here. | ||||
| 	if err := pdeath.Restore(); err != nil { | ||||
| 		return fmt.Errorf("can't restore pdeath signal: %w", err) | ||||
| 	} | ||||
| 	// Compare the parent from the initial start of the init process and make | ||||
| 	// sure that it did not change.  if the parent changes that means it died | ||||
| 	// and we were reparented to something else so we should just kill ourself | ||||
| 	// and not cause problems for someone else. | ||||
| 	if unix.Getppid() != l.parentPid { | ||||
| 		return unix.Kill(unix.Getpid(), unix.SIGKILL) | ||||
| 	} | ||||
| 	// Check for the arg before waiting to make sure it exists and it is | ||||
| 	// returned as a create time error. | ||||
| 	name, err := exec.LookPath(l.config.Args[0]) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	// exec.LookPath in Go < 1.20 might return no error for an executable | ||||
| 	// residing on a file system mounted with noexec flag, so perform this | ||||
| 	// extra check now while we can still return a proper error. | ||||
| 	// TODO: remove this once go < 1.20 is not supported. | ||||
| 	if err := eaccess(name); err != nil { | ||||
| 		return &os.PathError{Op: "eaccess", Path: name, Err: err} | ||||
| 	} | ||||
|  | ||||
| 	// Set seccomp as close to execve as possible, so as few syscalls take | ||||
| 	// place afterward (reducing the amount of syscalls that users need to | ||||
| 	// enable in their seccomp profiles). However, this needs to be done | ||||
| 	// before closing the pipe since we need it to pass the seccompFd to | ||||
| 	// the parent. | ||||
| 	if l.config.Config.Seccomp != nil && l.config.NoNewPrivileges { | ||||
| 		seccompFd, err := seccomp.InitSeccomp(l.config.Config.Seccomp) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("unable to init seccomp: %w", err) | ||||
| 		} | ||||
|  | ||||
| 		if err := syncParentSeccomp(l.pipe, seccompFd); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	// Close the pipe to signal that we have completed our init. | ||||
| 	logrus.Debugf("init: closing the pipe to signal completion") | ||||
| 	_ = l.pipe.Close() | ||||
|  | ||||
| 	// Close the log pipe fd so the parent's ForwardLogs can exit. | ||||
| 	if err := unix.Close(l.logFd); err != nil { | ||||
| 		return &os.PathError{Op: "close log pipe", Path: "fd " + strconv.Itoa(l.logFd), Err: err} | ||||
| 	} | ||||
|  | ||||
| 	// Wait for the FIFO to be opened on the other side before exec-ing the | ||||
| 	// user process. We open it through /proc/self/fd/$fd, because the fd that | ||||
| 	// was given to us was an O_PATH fd to the fifo itself. Linux allows us to | ||||
| 	// re-open an O_PATH fd through /proc. | ||||
| 	fifoPath := "/proc/self/fd/" + strconv.Itoa(l.fifoFd) | ||||
| 	fd, err := unix.Open(fifoPath, unix.O_WRONLY|unix.O_CLOEXEC, 0) | ||||
| 	if err != nil { | ||||
| 		return &os.PathError{Op: "open exec fifo", Path: fifoPath, Err: err} | ||||
| 	} | ||||
| 	if _, err := unix.Write(fd, []byte("0")); err != nil { | ||||
| 		return &os.PathError{Op: "write exec fifo", Path: fifoPath, Err: err} | ||||
| 	} | ||||
|  | ||||
| 	// Close the O_PATH fifofd fd before exec because the kernel resets | ||||
| 	// dumpable in the wrong order. This has been fixed in newer kernels, but | ||||
| 	// we keep this to ensure CVE-2016-9962 doesn't re-emerge on older kernels. | ||||
| 	// N.B. the core issue itself (passing dirfds to the host filesystem) has | ||||
| 	// since been resolved. | ||||
| 	// https://github.com/torvalds/linux/blob/v4.9/fs/exec.c#L1290-L1318 | ||||
| 	_ = unix.Close(l.fifoFd) | ||||
|  | ||||
| 	s := l.config.SpecState | ||||
| 	s.Pid = unix.Getpid() | ||||
| 	s.Status = specs.StateCreated | ||||
| 	if err := l.config.Config.Hooks[configs.StartContainer].RunHooks(s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Close all file descriptors we are not passing to the container. This is | ||||
| 	// necessary because the execve target could use internal runc fds as the | ||||
| 	// execve path, potentially giving access to binary files from the host | ||||
| 	// (which can then be opened by container processes, leading to container | ||||
| 	// escapes). Note that because this operation will close any open file | ||||
| 	// descriptors that are referenced by (*os.File) handles from underneath | ||||
| 	// the Go runtime, we must not do any file operations after this point | ||||
| 	// (otherwise the (*os.File) finaliser could close the wrong file). See | ||||
| 	// CVE-2024-21626 for more information as to why this protection is | ||||
| 	// necessary. | ||||
| 	// | ||||
| 	// This is not needed for runc-dmz, because the extra execve(2) step means | ||||
| 	// that all O_CLOEXEC file descriptors have already been closed and thus | ||||
| 	// the second execve(2) from runc-dmz cannot access internal file | ||||
| 	// descriptors from runc. | ||||
| 	if err := utils.UnsafeCloseFrom(l.config.PassedFilesCount + 3); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return system.Exec(name, l.config.Args[0:], os.Environ()) | ||||
| } | ||||
							
								
								
									
										243
									
								
								vendor/github.com/opencontainers/runc/libcontainer/state_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										243
									
								
								vendor/github.com/opencontainers/runc/libcontainer/state_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,243 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/configs" | ||||
| 	"github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| func newStateTransitionError(from, to containerState) error { | ||||
| 	return &stateTransitionError{ | ||||
| 		From: from.status().String(), | ||||
| 		To:   to.status().String(), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // stateTransitionError is returned when an invalid state transition happens from one | ||||
| // state to another. | ||||
| type stateTransitionError struct { | ||||
| 	From string | ||||
| 	To   string | ||||
| } | ||||
|  | ||||
| func (s *stateTransitionError) Error() string { | ||||
| 	return fmt.Sprintf("invalid state transition from %s to %s", s.From, s.To) | ||||
| } | ||||
|  | ||||
| type containerState interface { | ||||
| 	transition(containerState) error | ||||
| 	destroy() error | ||||
| 	status() Status | ||||
| } | ||||
|  | ||||
| func destroy(c *linuxContainer) error { | ||||
| 	if !c.config.Namespaces.Contains(configs.NEWPID) || | ||||
| 		c.config.Namespaces.PathOf(configs.NEWPID) != "" { | ||||
| 		if err := signalAllProcesses(c.cgroupManager, unix.SIGKILL); err != nil { | ||||
| 			logrus.Warn(err) | ||||
| 		} | ||||
| 	} | ||||
| 	err := c.cgroupManager.Destroy() | ||||
| 	if c.intelRdtManager != nil { | ||||
| 		if ierr := c.intelRdtManager.Destroy(); err == nil { | ||||
| 			err = ierr | ||||
| 		} | ||||
| 	} | ||||
| 	if rerr := os.RemoveAll(c.root); err == nil { | ||||
| 		err = rerr | ||||
| 	} | ||||
| 	c.initProcess = nil | ||||
| 	if herr := runPoststopHooks(c); err == nil { | ||||
| 		err = herr | ||||
| 	} | ||||
| 	c.state = &stoppedState{c: c} | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func runPoststopHooks(c *linuxContainer) error { | ||||
| 	hooks := c.config.Hooks | ||||
| 	if hooks == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	s, err := c.currentOCIState() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	s.Status = specs.StateStopped | ||||
|  | ||||
| 	if err := hooks[configs.Poststop].RunHooks(s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // stoppedState represents a container is a stopped/destroyed state. | ||||
| type stoppedState struct { | ||||
| 	c *linuxContainer | ||||
| } | ||||
|  | ||||
| func (b *stoppedState) status() Status { | ||||
| 	return Stopped | ||||
| } | ||||
|  | ||||
| func (b *stoppedState) transition(s containerState) error { | ||||
| 	switch s.(type) { | ||||
| 	case *runningState, *restoredState: | ||||
| 		b.c.state = s | ||||
| 		return nil | ||||
| 	case *stoppedState: | ||||
| 		return nil | ||||
| 	} | ||||
| 	return newStateTransitionError(b, s) | ||||
| } | ||||
|  | ||||
| func (b *stoppedState) destroy() error { | ||||
| 	return destroy(b.c) | ||||
| } | ||||
|  | ||||
| // runningState represents a container that is currently running. | ||||
| type runningState struct { | ||||
| 	c *linuxContainer | ||||
| } | ||||
|  | ||||
| func (r *runningState) status() Status { | ||||
| 	return Running | ||||
| } | ||||
|  | ||||
| func (r *runningState) transition(s containerState) error { | ||||
| 	switch s.(type) { | ||||
| 	case *stoppedState: | ||||
| 		if r.c.runType() == Running { | ||||
| 			return ErrRunning | ||||
| 		} | ||||
| 		r.c.state = s | ||||
| 		return nil | ||||
| 	case *pausedState: | ||||
| 		r.c.state = s | ||||
| 		return nil | ||||
| 	case *runningState: | ||||
| 		return nil | ||||
| 	} | ||||
| 	return newStateTransitionError(r, s) | ||||
| } | ||||
|  | ||||
| func (r *runningState) destroy() error { | ||||
| 	if r.c.runType() == Running { | ||||
| 		return ErrRunning | ||||
| 	} | ||||
| 	return destroy(r.c) | ||||
| } | ||||
|  | ||||
| type createdState struct { | ||||
| 	c *linuxContainer | ||||
| } | ||||
|  | ||||
| func (i *createdState) status() Status { | ||||
| 	return Created | ||||
| } | ||||
|  | ||||
| func (i *createdState) transition(s containerState) error { | ||||
| 	switch s.(type) { | ||||
| 	case *runningState, *pausedState, *stoppedState: | ||||
| 		i.c.state = s | ||||
| 		return nil | ||||
| 	case *createdState: | ||||
| 		return nil | ||||
| 	} | ||||
| 	return newStateTransitionError(i, s) | ||||
| } | ||||
|  | ||||
| func (i *createdState) destroy() error { | ||||
| 	_ = i.c.initProcess.signal(unix.SIGKILL) | ||||
| 	return destroy(i.c) | ||||
| } | ||||
|  | ||||
| // pausedState represents a container that is currently pause.  It cannot be destroyed in a | ||||
| // paused state and must transition back to running first. | ||||
| type pausedState struct { | ||||
| 	c *linuxContainer | ||||
| } | ||||
|  | ||||
| func (p *pausedState) status() Status { | ||||
| 	return Paused | ||||
| } | ||||
|  | ||||
| func (p *pausedState) transition(s containerState) error { | ||||
| 	switch s.(type) { | ||||
| 	case *runningState, *stoppedState: | ||||
| 		p.c.state = s | ||||
| 		return nil | ||||
| 	case *pausedState: | ||||
| 		return nil | ||||
| 	} | ||||
| 	return newStateTransitionError(p, s) | ||||
| } | ||||
|  | ||||
| func (p *pausedState) destroy() error { | ||||
| 	t := p.c.runType() | ||||
| 	if t != Running && t != Created { | ||||
| 		if err := p.c.cgroupManager.Freeze(configs.Thawed); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		return destroy(p.c) | ||||
| 	} | ||||
| 	return ErrPaused | ||||
| } | ||||
|  | ||||
| // restoredState is the same as the running state but also has associated checkpoint | ||||
| // information that maybe need destroyed when the container is stopped and destroy is called. | ||||
| type restoredState struct { | ||||
| 	imageDir string | ||||
| 	c        *linuxContainer | ||||
| } | ||||
|  | ||||
| func (r *restoredState) status() Status { | ||||
| 	return Running | ||||
| } | ||||
|  | ||||
| func (r *restoredState) transition(s containerState) error { | ||||
| 	switch s.(type) { | ||||
| 	case *stoppedState, *runningState: | ||||
| 		return nil | ||||
| 	} | ||||
| 	return newStateTransitionError(r, s) | ||||
| } | ||||
|  | ||||
| func (r *restoredState) destroy() error { | ||||
| 	if _, err := os.Stat(filepath.Join(r.c.root, "checkpoint")); err != nil { | ||||
| 		if !os.IsNotExist(err) { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return destroy(r.c) | ||||
| } | ||||
|  | ||||
| // loadedState is used whenever a container is restored, loaded, or setting additional | ||||
| // processes inside and it should not be destroyed when it is exiting. | ||||
| type loadedState struct { | ||||
| 	c *linuxContainer | ||||
| 	s Status | ||||
| } | ||||
|  | ||||
| func (n *loadedState) status() Status { | ||||
| 	return n.s | ||||
| } | ||||
|  | ||||
| func (n *loadedState) transition(s containerState) error { | ||||
| 	n.c.state = s | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (n *loadedState) destroy() error { | ||||
| 	if err := n.c.refreshState(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return n.c.state.destroy() | ||||
| } | ||||
							
								
								
									
										13
									
								
								vendor/github.com/opencontainers/runc/libcontainer/stats_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/opencontainers/runc/libcontainer/stats_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,13 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"github.com/opencontainers/runc/libcontainer/cgroups" | ||||
| 	"github.com/opencontainers/runc/libcontainer/intelrdt" | ||||
| 	"github.com/opencontainers/runc/types" | ||||
| ) | ||||
|  | ||||
| type Stats struct { | ||||
| 	Interfaces    []*types.NetworkInterface | ||||
| 	CgroupStats   *cgroups.Stats | ||||
| 	IntelRdtStats *intelrdt.Stats | ||||
| } | ||||
							
								
								
									
										126
									
								
								vendor/github.com/opencontainers/runc/libcontainer/sync.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										126
									
								
								vendor/github.com/opencontainers/runc/libcontainer/sync.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,126 +0,0 @@ | ||||
| package libcontainer | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
|  | ||||
| 	"github.com/opencontainers/runc/libcontainer/utils" | ||||
| ) | ||||
|  | ||||
| type syncType string | ||||
|  | ||||
| // Constants that are used for synchronisation between the parent and child | ||||
| // during container setup. They come in pairs (with procError being a generic | ||||
| // response which is followed by an &initError). | ||||
| // | ||||
| //	[  child  ] <-> [   parent   ] | ||||
| // | ||||
| //	procHooks   --> [run hooks] | ||||
| //	            <-- procResume | ||||
| // | ||||
| //	procReady   --> [final setup] | ||||
| //	            <-- procRun | ||||
| // | ||||
| //	procSeccomp --> [pick up seccomp fd with pidfd_getfd()] | ||||
| //	            <-- procSeccompDone | ||||
| const ( | ||||
| 	procError       syncType = "procError" | ||||
| 	procReady       syncType = "procReady" | ||||
| 	procRun         syncType = "procRun" | ||||
| 	procHooks       syncType = "procHooks" | ||||
| 	procResume      syncType = "procResume" | ||||
| 	procSeccomp     syncType = "procSeccomp" | ||||
| 	procSeccompDone syncType = "procSeccompDone" | ||||
| ) | ||||
|  | ||||
| type syncT struct { | ||||
| 	Type syncType `json:"type"` | ||||
| 	Fd   int      `json:"fd"` | ||||
| } | ||||
|  | ||||
| // initError is used to wrap errors for passing them via JSON, | ||||
| // as encoding/json can't unmarshal into error type. | ||||
| type initError struct { | ||||
| 	Message string `json:"message,omitempty"` | ||||
| } | ||||
|  | ||||
| func (i initError) Error() string { | ||||
| 	return i.Message | ||||
| } | ||||
|  | ||||
| // writeSync is used to write to a synchronisation pipe. An error is returned | ||||
| // if there was a problem writing the payload. | ||||
| func writeSync(pipe io.Writer, sync syncType) error { | ||||
| 	return writeSyncWithFd(pipe, sync, -1) | ||||
| } | ||||
|  | ||||
| // writeSyncWithFd is used to write to a synchronisation pipe. An error is | ||||
| // returned if there was a problem writing the payload. | ||||
| func writeSyncWithFd(pipe io.Writer, sync syncType, fd int) error { | ||||
| 	if err := utils.WriteJSON(pipe, syncT{sync, fd}); err != nil { | ||||
| 		return fmt.Errorf("writing syncT %q: %w", string(sync), err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // readSync is used to read from a synchronisation pipe. An error is returned | ||||
| // if we got an initError, the pipe was closed, or we got an unexpected flag. | ||||
| func readSync(pipe io.Reader, expected syncType) error { | ||||
| 	var procSync syncT | ||||
| 	if err := json.NewDecoder(pipe).Decode(&procSync); err != nil { | ||||
| 		if errors.Is(err, io.EOF) { | ||||
| 			return errors.New("parent closed synchronisation channel") | ||||
| 		} | ||||
| 		return fmt.Errorf("failed reading error from parent: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	if procSync.Type == procError { | ||||
| 		var ierr initError | ||||
|  | ||||
| 		if err := json.NewDecoder(pipe).Decode(&ierr); err != nil { | ||||
| 			return fmt.Errorf("failed reading error from parent: %w", err) | ||||
| 		} | ||||
|  | ||||
| 		return &ierr | ||||
| 	} | ||||
|  | ||||
| 	if procSync.Type != expected { | ||||
| 		return errors.New("invalid synchronisation flag from parent") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // parseSync runs the given callback function on each syncT received from the | ||||
| // child. It will return once io.EOF is returned from the given pipe. | ||||
| func parseSync(pipe io.Reader, fn func(*syncT) error) error { | ||||
| 	dec := json.NewDecoder(pipe) | ||||
| 	for { | ||||
| 		var sync syncT | ||||
| 		if err := dec.Decode(&sync); err != nil { | ||||
| 			if errors.Is(err, io.EOF) { | ||||
| 				break | ||||
| 			} | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		// We handle this case outside fn for cleanliness reasons. | ||||
| 		var ierr *initError | ||||
| 		if sync.Type == procError { | ||||
| 			if err := dec.Decode(&ierr); err != nil && !errors.Is(err, io.EOF) { | ||||
| 				return fmt.Errorf("error decoding proc error from init: %w", err) | ||||
| 			} | ||||
| 			if ierr != nil { | ||||
| 				return ierr | ||||
| 			} | ||||
| 			// Programmer error. | ||||
| 			panic("No error following JSON procError payload.") | ||||
| 		} | ||||
|  | ||||
| 		if err := fn(&sync); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										155
									
								
								vendor/github.com/opencontainers/runc/types/events.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										155
									
								
								vendor/github.com/opencontainers/runc/types/events.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,155 +0,0 @@ | ||||
| package types | ||||
|  | ||||
| import "github.com/opencontainers/runc/libcontainer/intelrdt" | ||||
|  | ||||
| // Event struct for encoding the event data to json. | ||||
| type Event struct { | ||||
| 	Type string      `json:"type"` | ||||
| 	ID   string      `json:"id"` | ||||
| 	Data interface{} `json:"data,omitempty"` | ||||
| } | ||||
|  | ||||
| // stats is the runc specific stats structure for stability when encoding and decoding stats. | ||||
| type Stats struct { | ||||
| 	CPU               Cpu                 `json:"cpu"` | ||||
| 	CPUSet            CPUSet              `json:"cpuset"` | ||||
| 	Memory            Memory              `json:"memory"` | ||||
| 	Pids              Pids                `json:"pids"` | ||||
| 	Blkio             Blkio               `json:"blkio"` | ||||
| 	Hugetlb           map[string]Hugetlb  `json:"hugetlb"` | ||||
| 	IntelRdt          IntelRdt            `json:"intel_rdt"` | ||||
| 	NetworkInterfaces []*NetworkInterface `json:"network_interfaces"` | ||||
| } | ||||
|  | ||||
| type Hugetlb struct { | ||||
| 	Usage   uint64 `json:"usage,omitempty"` | ||||
| 	Max     uint64 `json:"max,omitempty"` | ||||
| 	Failcnt uint64 `json:"failcnt"` | ||||
| } | ||||
|  | ||||
| type BlkioEntry struct { | ||||
| 	Major uint64 `json:"major,omitempty"` | ||||
| 	Minor uint64 `json:"minor,omitempty"` | ||||
| 	Op    string `json:"op,omitempty"` | ||||
| 	Value uint64 `json:"value,omitempty"` | ||||
| } | ||||
|  | ||||
| type Blkio struct { | ||||
| 	IoServiceBytesRecursive []BlkioEntry `json:"ioServiceBytesRecursive,omitempty"` | ||||
| 	IoServicedRecursive     []BlkioEntry `json:"ioServicedRecursive,omitempty"` | ||||
| 	IoQueuedRecursive       []BlkioEntry `json:"ioQueueRecursive,omitempty"` | ||||
| 	IoServiceTimeRecursive  []BlkioEntry `json:"ioServiceTimeRecursive,omitempty"` | ||||
| 	IoWaitTimeRecursive     []BlkioEntry `json:"ioWaitTimeRecursive,omitempty"` | ||||
| 	IoMergedRecursive       []BlkioEntry `json:"ioMergedRecursive,omitempty"` | ||||
| 	IoTimeRecursive         []BlkioEntry `json:"ioTimeRecursive,omitempty"` | ||||
| 	SectorsRecursive        []BlkioEntry `json:"sectorsRecursive,omitempty"` | ||||
| } | ||||
|  | ||||
| type Pids struct { | ||||
| 	Current uint64 `json:"current,omitempty"` | ||||
| 	Limit   uint64 `json:"limit,omitempty"` | ||||
| } | ||||
|  | ||||
| type Throttling struct { | ||||
| 	Periods          uint64 `json:"periods,omitempty"` | ||||
| 	ThrottledPeriods uint64 `json:"throttledPeriods,omitempty"` | ||||
| 	ThrottledTime    uint64 `json:"throttledTime,omitempty"` | ||||
| } | ||||
|  | ||||
| type CpuUsage struct { | ||||
| 	// Units: nanoseconds. | ||||
| 	Total        uint64   `json:"total,omitempty"` | ||||
| 	Percpu       []uint64 `json:"percpu,omitempty"` | ||||
| 	PercpuKernel []uint64 `json:"percpu_kernel,omitempty"` | ||||
| 	PercpuUser   []uint64 `json:"percpu_user,omitempty"` | ||||
| 	Kernel       uint64   `json:"kernel"` | ||||
| 	User         uint64   `json:"user"` | ||||
| } | ||||
|  | ||||
| type Cpu struct { | ||||
| 	Usage      CpuUsage   `json:"usage,omitempty"` | ||||
| 	Throttling Throttling `json:"throttling,omitempty"` | ||||
| } | ||||
|  | ||||
| type CPUSet struct { | ||||
| 	CPUs                  []uint16 `json:"cpus,omitempty"` | ||||
| 	CPUExclusive          uint64   `json:"cpu_exclusive"` | ||||
| 	Mems                  []uint16 `json:"mems,omitempty"` | ||||
| 	MemHardwall           uint64   `json:"mem_hardwall"` | ||||
| 	MemExclusive          uint64   `json:"mem_exclusive"` | ||||
| 	MemoryMigrate         uint64   `json:"memory_migrate"` | ||||
| 	MemorySpreadPage      uint64   `json:"memory_spread_page"` | ||||
| 	MemorySpreadSlab      uint64   `json:"memory_spread_slab"` | ||||
| 	MemoryPressure        uint64   `json:"memory_pressure"` | ||||
| 	SchedLoadBalance      uint64   `json:"sched_load_balance"` | ||||
| 	SchedRelaxDomainLevel int64    `json:"sched_relax_domain_level"` | ||||
| } | ||||
|  | ||||
| type MemoryEntry struct { | ||||
| 	Limit   uint64 `json:"limit"` | ||||
| 	Usage   uint64 `json:"usage,omitempty"` | ||||
| 	Max     uint64 `json:"max,omitempty"` | ||||
| 	Failcnt uint64 `json:"failcnt"` | ||||
| } | ||||
|  | ||||
| type Memory struct { | ||||
| 	Cache     uint64            `json:"cache,omitempty"` | ||||
| 	Usage     MemoryEntry       `json:"usage,omitempty"` | ||||
| 	Swap      MemoryEntry       `json:"swap,omitempty"` | ||||
| 	Kernel    MemoryEntry       `json:"kernel,omitempty"` | ||||
| 	KernelTCP MemoryEntry       `json:"kernelTCP,omitempty"` | ||||
| 	Raw       map[string]uint64 `json:"raw,omitempty"` | ||||
| } | ||||
|  | ||||
| type L3CacheInfo struct { | ||||
| 	CbmMask    string `json:"cbm_mask,omitempty"` | ||||
| 	MinCbmBits uint64 `json:"min_cbm_bits,omitempty"` | ||||
| 	NumClosids uint64 `json:"num_closids,omitempty"` | ||||
| } | ||||
|  | ||||
| type MemBwInfo struct { | ||||
| 	BandwidthGran uint64 `json:"bandwidth_gran,omitempty"` | ||||
| 	DelayLinear   uint64 `json:"delay_linear,omitempty"` | ||||
| 	MinBandwidth  uint64 `json:"min_bandwidth,omitempty"` | ||||
| 	NumClosids    uint64 `json:"num_closids,omitempty"` | ||||
| } | ||||
|  | ||||
| type IntelRdt struct { | ||||
| 	// The read-only L3 cache information | ||||
| 	L3CacheInfo *L3CacheInfo `json:"l3_cache_info,omitempty"` | ||||
|  | ||||
| 	// The read-only L3 cache schema in root | ||||
| 	L3CacheSchemaRoot string `json:"l3_cache_schema_root,omitempty"` | ||||
|  | ||||
| 	// The L3 cache schema in 'container_id' group | ||||
| 	L3CacheSchema string `json:"l3_cache_schema,omitempty"` | ||||
|  | ||||
| 	// The read-only memory bandwidth information | ||||
| 	MemBwInfo *MemBwInfo `json:"mem_bw_info,omitempty"` | ||||
|  | ||||
| 	// The read-only memory bandwidth schema in root | ||||
| 	MemBwSchemaRoot string `json:"mem_bw_schema_root,omitempty"` | ||||
|  | ||||
| 	// The memory bandwidth schema in 'container_id' group | ||||
| 	MemBwSchema string `json:"mem_bw_schema,omitempty"` | ||||
|  | ||||
| 	// The memory bandwidth monitoring statistics from NUMA nodes in 'container_id' group | ||||
| 	MBMStats *[]intelrdt.MBMNumaNodeStats `json:"mbm_stats,omitempty"` | ||||
|  | ||||
| 	// The cache monitoring technology statistics from NUMA nodes in 'container_id' group | ||||
| 	CMTStats *[]intelrdt.CMTNumaNodeStats `json:"cmt_stats,omitempty"` | ||||
| } | ||||
|  | ||||
| type NetworkInterface struct { | ||||
| 	// Name is the name of the network interface. | ||||
| 	Name string | ||||
|  | ||||
| 	RxBytes   uint64 | ||||
| 	RxPackets uint64 | ||||
| 	RxErrors  uint64 | ||||
| 	RxDropped uint64 | ||||
| 	TxBytes   uint64 | ||||
| 	TxPackets uint64 | ||||
| 	TxErrors  uint64 | ||||
| 	TxDropped uint64 | ||||
| } | ||||
							
								
								
									
										4
									
								
								vendor/github.com/seccomp/libseccomp-golang/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/seccomp/libseccomp-golang/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +0,0 @@ | ||||
| *~ | ||||
| *.swp | ||||
| *.orig | ||||
| tags | ||||
							
								
								
									
										4
									
								
								vendor/github.com/seccomp/libseccomp-golang/.golangci.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/seccomp/libseccomp-golang/.golangci.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +0,0 @@ | ||||
| # For documentation, see https://golangci-lint.run/usage/configuration/ | ||||
| linters: | ||||
|   enable: | ||||
|     - gofumpt | ||||
							
								
								
									
										42
									
								
								vendor/github.com/seccomp/libseccomp-golang/CHANGELOG
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										42
									
								
								vendor/github.com/seccomp/libseccomp-golang/CHANGELOG
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,42 +0,0 @@ | ||||
| libseccomp-golang: Releases | ||||
| =============================================================================== | ||||
| https://github.com/seccomp/libseccomp-golang | ||||
|  | ||||
| * Version 0.10.0 - June 9, 2022 | ||||
| - Minimum supported version of libseccomp bumped to v2.3.1 | ||||
| - Add seccomp userspace notification API (ActNotify, filter.*Notif*) | ||||
| - Add filter.{Get,Set}SSB (to support SCMP_FLTATR_CTL_SSB) | ||||
| - Add filter.{Get,Set}Optimize (to support SCMP_FLTATR_CTL_OPTIMIZE) | ||||
| - Add filter.{Get,Set}RawRC (to support SCMP_FLTATR_API_SYSRAWRC) | ||||
| - Add ArchPARISC, ArchPARISC64, ArchRISCV64 | ||||
| - Add ActKillProcess and ActKillThread; deprecate ActKill | ||||
| - Add go module support | ||||
| - Return ErrSyscallDoesNotExist when unable to resolve a syscall | ||||
| - Fix some functions to check for both kernel level API and libseccomp version | ||||
| - Fix MakeCondition to use sanitizeCompareOp | ||||
| - Fix AddRule to handle EACCES (from libseccomp >= 2.5.0) | ||||
| - Updated the main docs and converted to README.md | ||||
| - Added CONTRIBUTING.md, SECURITY.md, and administrative docs under doc/admin | ||||
| - Add GitHub action CI, enable more linters | ||||
| - test: test against various libseccomp versions | ||||
| - test: fix and simplify execInSubprocess | ||||
| - test: fix APILevelIsSupported | ||||
| - Refactor the Errno(-1 * retCode) pattern | ||||
| - Refactor/unify libseccomp version / API level checks | ||||
| - Code cleanups (linter, formatting, spelling fixes) | ||||
| - Cleanup: use errors.New instead of fmt.Errorf where appropriate | ||||
| - Cleanup: remove duplicated cgo stuff, redundant linux build tag | ||||
|  | ||||
| * Version 0.9.1 - May 21, 2019 | ||||
| - Minimum supported version of libseccomp bumped to v2.2.0 | ||||
| - Use Libseccomp's `seccomp_version` API to retrieve library version | ||||
| - Unconditionally set TSync attribute for filters, due to Go's heavily threaded nature | ||||
| - Fix CVE-2017-18367 - Multiple syscall arguments were incorrectly combined with logical-OR, instead of logical-AND | ||||
| - Fix a failure to build on Debian-based distributions due to CGo code | ||||
| - Fix unit test failures on 32-bit architectures | ||||
| - Improve several errors to be more verbose about their causes | ||||
| - Add support for SCMP_ACT_LOG (with libseccomp versions 2.4.x and higher), permitting syscalls but logging their execution | ||||
| - Add support for SCMP_FLTATR_CTL_LOG (with libseccomp versions 2.4.x and higher), logging not-allowed actions when they are denied | ||||
|  | ||||
| * Version 0.9.0 - January 5, 2017 | ||||
| - Initial tagged release | ||||
							
								
								
									
										120
									
								
								vendor/github.com/seccomp/libseccomp-golang/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										120
									
								
								vendor/github.com/seccomp/libseccomp-golang/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,120 +0,0 @@ | ||||
| How to Submit Patches to the libseccomp-golang Project | ||||
| =============================================================================== | ||||
| https://github.com/seccomp/libseccomp-golang | ||||
|  | ||||
| This document is intended to act as a guide to help you contribute to the | ||||
| libseccomp-golang project.  It is not perfect, and there will always be | ||||
| exceptions to the rules described here, but by following the instructions below | ||||
| you should have a much easier time getting your work merged with the upstream | ||||
| project. | ||||
|  | ||||
| ## Test Your Code Using Existing Tests | ||||
|  | ||||
| A number of tests and lint related recipes are provided in the Makefile, if | ||||
| you want to run the standard regression tests, you can execute the following: | ||||
|  | ||||
| 	# make check | ||||
|  | ||||
| In order to use it, the 'golangci-lint' tool is needed, which can be found at: | ||||
|  | ||||
| * https://github.com/golangci/golangci-lint | ||||
|  | ||||
| ## Add New Tests for New Functionality | ||||
|  | ||||
| Any submissions which add functionality, or significantly change the existing | ||||
| code, should include additional tests to verify the proper operation of the | ||||
| proposed changes. | ||||
|  | ||||
| ## Explain Your Work | ||||
|  | ||||
| At the top of every patch you should include a description of the problem you | ||||
| are trying to solve, how you solved it, and why you chose the solution you | ||||
| implemented.  If you are submitting a bug fix, it is also incredibly helpful | ||||
| if you can describe/include a reproducer for the problem in the description as | ||||
| well as instructions on how to test for the bug and verify that it has been | ||||
| fixed. | ||||
|  | ||||
| ## Sign Your Work | ||||
|  | ||||
| The sign-off is a simple line at the end of the patch description, which | ||||
| certifies that you wrote it or otherwise have the right to pass it on as an | ||||
| open-source patch.  The "Developer's Certificate of Origin" pledge is taken | ||||
| from the Linux Kernel and the rules are pretty simple: | ||||
|  | ||||
| 	Developer's Certificate of Origin 1.1 | ||||
|  | ||||
| 	By making a contribution to this project, I certify that: | ||||
|  | ||||
| 	(a) The contribution was created in whole or in part by me and I | ||||
| 	    have the right to submit it under the open source license | ||||
| 	    indicated in the file; or | ||||
|  | ||||
| 	(b) The contribution is based upon previous work that, to the best | ||||
| 	    of my knowledge, is covered under an appropriate open source | ||||
| 	    license and I have the right under that license to submit that | ||||
| 	    work with modifications, whether created in whole or in part | ||||
| 	    by me, under the same open source license (unless I am | ||||
| 	    permitted to submit under a different license), as indicated | ||||
| 	    in the file; or | ||||
|  | ||||
| 	(c) The contribution was provided directly to me by some other | ||||
| 	    person who certified (a), (b) or (c) and I have not modified | ||||
| 	    it. | ||||
|  | ||||
| 	(d) I understand and agree that this project and the contribution | ||||
| 	    are public and that a record of the contribution (including all | ||||
| 	    personal information I submit with it, including my sign-off) is | ||||
| 	    maintained indefinitely and may be redistributed consistent with | ||||
| 	    this project or the open source license(s) involved. | ||||
|  | ||||
| ... then you just add a line to the bottom of your patch description, with | ||||
| your real name, saying: | ||||
|  | ||||
| 	Signed-off-by: Random J Developer <random@developer.example.org> | ||||
|  | ||||
| You can add this to your commit description in `git` with `git commit -s` | ||||
|  | ||||
| ## Post Your Patches Upstream | ||||
|  | ||||
| The libseccomp project accepts both GitHub pull requests and patches sent via | ||||
| the mailing list.  GitHub pull requests are preferred.  This sections below | ||||
| explain how to contribute via either method. Please read each step and perform | ||||
| all steps that apply to your chosen contribution method. | ||||
|  | ||||
| ### Submitting via Email | ||||
|  | ||||
| Depending on how you decided to work with the libseccomp code base and what | ||||
| tools you are using there are different ways to generate your patch(es). | ||||
| However, regardless of what tools you use, you should always generate your | ||||
| patches using the "unified" diff/patch format and the patches should always | ||||
| apply to the libseccomp source tree using the following command from the top | ||||
| directory of the libseccomp sources: | ||||
|  | ||||
| 	# patch -p1 < changes.patch | ||||
|  | ||||
| If you are not using git, stacked git (stgit), or some other tool which can | ||||
| generate patch files for you automatically, you may find the following command | ||||
| helpful in generating patches, where "libseccomp.orig/" is the unmodified | ||||
| source code directory and "libseccomp/" is the source code directory with your | ||||
| changes: | ||||
|  | ||||
| 	# diff -purN libseccomp.orig/ libseccomp/ | ||||
|  | ||||
| When in doubt please generate your patch and try applying it to an unmodified | ||||
| copy of the libseccomp sources; if it fails for you, it will fail for the rest | ||||
| of us. | ||||
|  | ||||
| Finally, you will need to email your patches to the mailing list so they can | ||||
| be reviewed and potentially merged into the main libseccomp repository.  When | ||||
| sending patches to the mailing list it is important to send your email in text | ||||
| form, no HTML mail please, and ensure that your email client does not mangle | ||||
| your patches.  It should be possible to save your raw email to disk and apply | ||||
| it directly to the libseccomp source code; if that fails then you likely have | ||||
| a problem with your email client.  When in doubt try a test first by sending | ||||
| yourself an email with your patch and attempting to apply the emailed patch to | ||||
| the libseccomp repository; if it fails for you, it will fail for the rest of | ||||
| us trying to test your patch and include it in the main libseccomp repository. | ||||
|  | ||||
| ### Submitting via GitHub | ||||
|  | ||||
| See [this guide](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request) if you've never done this before. | ||||
							
								
								
									
										22
									
								
								vendor/github.com/seccomp/libseccomp-golang/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/seccomp/libseccomp-golang/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,22 +0,0 @@ | ||||
| Copyright (c) 2015 Matthew Heon <mheon@redhat.com> | ||||
| Copyright (c) 2015 Paul Moore <pmoore@redhat.com> | ||||
| All rights reserved. | ||||
|  | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions are met: | ||||
| - Redistributions of source code must retain the above copyright notice, | ||||
|   this list of conditions and the following disclaimer. | ||||
| - Redistributions in binary form must reproduce the above copyright notice, | ||||
|   this list of conditions and the following disclaimer in the documentation | ||||
|   and/or other materials provided with the distribution. | ||||
|  | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||||
| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||
| FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||
| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||
| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||
| OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
							
								
								
									
										31
									
								
								vendor/github.com/seccomp/libseccomp-golang/Makefile
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										31
									
								
								vendor/github.com/seccomp/libseccomp-golang/Makefile
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,31 +0,0 @@ | ||||
| # libseccomp-golang | ||||
|  | ||||
| .PHONY: all check check-build check-syntax fix-syntax vet test lint | ||||
|  | ||||
| all: check-build | ||||
|  | ||||
| check: lint test | ||||
|  | ||||
| check-build: | ||||
| 	go build | ||||
|  | ||||
| check-syntax: | ||||
| 	gofmt -d . | ||||
|  | ||||
| fix-syntax: | ||||
| 	gofmt -w . | ||||
|  | ||||
| vet: | ||||
| 	go vet -v ./... | ||||
|  | ||||
| # Previous bugs have made the tests freeze until the timeout. Golang default | ||||
| # timeout for tests is 10 minutes, which is too long, considering current tests | ||||
| # can be executed in less than 1 second. Reduce the timeout, so problems can | ||||
| # be noticed earlier in the CI. | ||||
| TEST_TIMEOUT=10s | ||||
|  | ||||
| test: | ||||
| 	go test -v -timeout $(TEST_TIMEOUT) | ||||
|  | ||||
| lint: | ||||
| 	golangci-lint run . | ||||
							
								
								
									
										59
									
								
								vendor/github.com/seccomp/libseccomp-golang/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										59
									
								
								vendor/github.com/seccomp/libseccomp-golang/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,59 +0,0 @@ | ||||
|  | ||||
| =============================================================================== | ||||
| https://github.com/seccomp/libseccomp-golang | ||||
|  | ||||
| [](https://pkg.go.dev/github.com/seccomp/libseccomp-golang) | ||||
| [](https://github.com/seccomp/libseccomp-golang/actions/workflows/validate.yml) | ||||
| [](https://github.com/seccomp/libseccomp-golang/actions/workflows/test.yml) | ||||
|  | ||||
| The libseccomp library provides an easy to use, platform independent, interface | ||||
| to the Linux Kernel's syscall filtering mechanism.  The libseccomp API is | ||||
| designed to abstract away the underlying BPF based syscall filter language and | ||||
| present a more conventional function-call based filtering interface that should | ||||
| be familiar to, and easily adopted by, application developers. | ||||
|  | ||||
| The libseccomp-golang library provides a Go based interface to the libseccomp | ||||
| library. | ||||
|  | ||||
| ## Online Resources | ||||
|  | ||||
| The library source repository currently lives on GitHub at the following URLs: | ||||
|  | ||||
| * https://github.com/seccomp/libseccomp-golang | ||||
| * https://github.com/seccomp/libseccomp | ||||
|  | ||||
| Documentation for this package is also available at: | ||||
|  | ||||
| * https://pkg.go.dev/github.com/seccomp/libseccomp-golang | ||||
|  | ||||
| ## Verifying Releases | ||||
|  | ||||
| Starting with libseccomp-golang v0.10.0, the git tag corresponding to each | ||||
| release should be signed by one of the libseccomp-golang maintainers.  It is | ||||
| recommended that before use you verify the release tags using the following | ||||
| command: | ||||
|  | ||||
| 	% git tag -v <tag> | ||||
|  | ||||
| At present, only the following keys, specified via the fingerprints below, are | ||||
| authorized to sign official libseccomp-golang release tags: | ||||
|  | ||||
| 	Paul Moore <paul@paul-moore.com> | ||||
| 	7100 AADF AE6E 6E94 0D2E  0AD6 55E4 5A5A E8CA 7C8A | ||||
|  | ||||
| 	Tom Hromatka <tom.hromatka@oracle.com> | ||||
| 	47A6 8FCE 37C7 D702 4FD6  5E11 356C E62C 2B52 4099 | ||||
|  | ||||
| 	Kir Kolyshkin <kolyshkin@gmail.com> | ||||
| 	C242 8CD7 5720 FACD CF76  B6EA 17DE 5ECB 75A1 100E | ||||
|  | ||||
| More information on GnuPG and git tag verification can be found at their | ||||
| respective websites: https://git-scm.com/docs/git and https://gnupg.org. | ||||
|  | ||||
| ## Installing the package | ||||
|  | ||||
| 	% go get github.com/seccomp/libseccomp-golang | ||||
|  | ||||
| ## Contributing | ||||
|  | ||||
| See [CONTRIBUTING.md](CONTRIBUTING.md). | ||||
							
								
								
									
										48
									
								
								vendor/github.com/seccomp/libseccomp-golang/SECURITY.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								vendor/github.com/seccomp/libseccomp-golang/SECURITY.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,48 +0,0 @@ | ||||
| The libseccomp-golang Security Vulnerability Handling Process | ||||
| =============================================================================== | ||||
| https://github.com/seccomp/libseccomp-golang | ||||
|  | ||||
| This document document attempts to describe the processes through which | ||||
| sensitive security relevant bugs can be responsibly disclosed to the | ||||
| libseccomp-golang project and how the project maintainers should handle these | ||||
| reports.  Just like the other libseccomp-golang process documents, this | ||||
| document should be treated as a guiding document and not a hard, unyielding set | ||||
| of regulations; the bug reporters and project maintainers are encouraged to | ||||
| work together to address the issues as best they can, in a manner which works | ||||
| best for all parties involved. | ||||
|  | ||||
| ### Reporting Problems | ||||
|  | ||||
| Problems with the libseccomp-golang library that are not suitable for immediate | ||||
| public disclosure should be emailed to the current libseccomp-golang | ||||
| maintainers, the list is below.  We typically request at most a 90 day time | ||||
| period to address the issue before it is made public, but we will make every | ||||
| effort to address the issue as quickly as possible and shorten the disclosure | ||||
| window. | ||||
|  | ||||
| * Paul Moore, paul@paul-moore.com | ||||
| * Tom Hromatka, tom.hromatka@oracle.com | ||||
| * Kir Kolyshkin, kolyshkin@gmail.com | ||||
|  | ||||
| ### Resolving Sensitive Security Issues | ||||
|  | ||||
| Upon disclosure of a bug, the maintainers should work together to investigate | ||||
| the problem and decide on a solution.  In order to prevent an early disclosure | ||||
| of the problem, those working on the solution should do so privately and | ||||
| outside of the traditional libseccomp-golang development practices.  One | ||||
| possible solution to this is to leverage the GitHub "Security" functionality to | ||||
| create a private development fork that can be shared among the maintainers, and | ||||
| optionally the reporter.  A placeholder GitHub issue may be created, but | ||||
| details should remain extremely limited until such time as the problem has been | ||||
| fixed and responsibly disclosed.  If a CVE, or other tag, has been assigned to | ||||
| the problem, the GitHub issue title should include the vulnerability tag once | ||||
| the problem has been disclosed. | ||||
|  | ||||
| ### Public Disclosure | ||||
|  | ||||
| Whenever possible, responsible reporting and patching practices should be | ||||
| followed, including notification to the linux-distros and oss-security mailing | ||||
| lists. | ||||
|  | ||||
| * https://oss-security.openwall.org/wiki/mailing-lists/distros | ||||
| * https://oss-security.openwall.org/wiki/mailing-lists/oss-security | ||||
							
								
								
									
										1188
									
								
								vendor/github.com/seccomp/libseccomp-golang/seccomp.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1188
									
								
								vendor/github.com/seccomp/libseccomp-golang/seccomp.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										884
									
								
								vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										884
									
								
								vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,884 +0,0 @@ | ||||
| // Internal functions for libseccomp Go bindings | ||||
| // No exported functions | ||||
|  | ||||
| package seccomp | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"syscall" | ||||
| ) | ||||
|  | ||||
| // Unexported C wrapping code - provides the C-Golang interface | ||||
| // Get the seccomp header in scope | ||||
| // Need stdlib.h for free() on cstrings | ||||
|  | ||||
| // To compile libseccomp-golang against a specific version of libseccomp: | ||||
| // cd ../libseccomp && mkdir -p prefix | ||||
| // ./configure --prefix=$PWD/prefix && make && make install | ||||
| // cd ../libseccomp-golang | ||||
| // PKG_CONFIG_PATH=$PWD/../libseccomp/prefix/lib/pkgconfig/ make | ||||
| // LD_PRELOAD=$PWD/../libseccomp/prefix/lib/libseccomp.so.2.5.0 PKG_CONFIG_PATH=$PWD/../libseccomp/prefix/lib/pkgconfig/ make test | ||||
|  | ||||
| // #cgo pkg-config: libseccomp | ||||
| /* | ||||
| #include <errno.h> | ||||
| #include <stdlib.h> | ||||
| #include <seccomp.h> | ||||
|  | ||||
| #if (SCMP_VER_MAJOR < 2) || \ | ||||
|     (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 3) || \ | ||||
|     (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR == 3 && SCMP_VER_MICRO < 1) | ||||
| #error This package requires libseccomp >= v2.3.1 | ||||
| #endif | ||||
|  | ||||
| #define ARCH_BAD ~0 | ||||
|  | ||||
| const uint32_t C_ARCH_BAD = ARCH_BAD; | ||||
|  | ||||
| #ifndef SCMP_ARCH_PPC | ||||
| #define SCMP_ARCH_PPC ARCH_BAD | ||||
| #endif | ||||
|  | ||||
| #ifndef SCMP_ARCH_PPC64 | ||||
| #define SCMP_ARCH_PPC64 ARCH_BAD | ||||
| #endif | ||||
|  | ||||
| #ifndef SCMP_ARCH_PPC64LE | ||||
| #define SCMP_ARCH_PPC64LE ARCH_BAD | ||||
| #endif | ||||
|  | ||||
| #ifndef SCMP_ARCH_S390 | ||||
| #define SCMP_ARCH_S390 ARCH_BAD | ||||
| #endif | ||||
|  | ||||
| #ifndef SCMP_ARCH_S390X | ||||
| #define SCMP_ARCH_S390X ARCH_BAD | ||||
| #endif | ||||
|  | ||||
| #ifndef SCMP_ARCH_PARISC | ||||
| #define SCMP_ARCH_PARISC ARCH_BAD | ||||
| #endif | ||||
|  | ||||
| #ifndef SCMP_ARCH_PARISC64 | ||||
| #define SCMP_ARCH_PARISC64 ARCH_BAD | ||||
| #endif | ||||
|  | ||||
| #ifndef SCMP_ARCH_RISCV64 | ||||
| #define SCMP_ARCH_RISCV64 ARCH_BAD | ||||
| #endif | ||||
|  | ||||
| const uint32_t C_ARCH_NATIVE       = SCMP_ARCH_NATIVE; | ||||
| const uint32_t C_ARCH_X86          = SCMP_ARCH_X86; | ||||
| const uint32_t C_ARCH_X86_64       = SCMP_ARCH_X86_64; | ||||
| const uint32_t C_ARCH_X32          = SCMP_ARCH_X32; | ||||
| const uint32_t C_ARCH_ARM          = SCMP_ARCH_ARM; | ||||
| const uint32_t C_ARCH_AARCH64      = SCMP_ARCH_AARCH64; | ||||
| const uint32_t C_ARCH_MIPS         = SCMP_ARCH_MIPS; | ||||
| const uint32_t C_ARCH_MIPS64       = SCMP_ARCH_MIPS64; | ||||
| const uint32_t C_ARCH_MIPS64N32    = SCMP_ARCH_MIPS64N32; | ||||
| const uint32_t C_ARCH_MIPSEL       = SCMP_ARCH_MIPSEL; | ||||
| const uint32_t C_ARCH_MIPSEL64     = SCMP_ARCH_MIPSEL64; | ||||
| const uint32_t C_ARCH_MIPSEL64N32  = SCMP_ARCH_MIPSEL64N32; | ||||
| const uint32_t C_ARCH_PPC          = SCMP_ARCH_PPC; | ||||
| const uint32_t C_ARCH_PPC64        = SCMP_ARCH_PPC64; | ||||
| const uint32_t C_ARCH_PPC64LE      = SCMP_ARCH_PPC64LE; | ||||
| const uint32_t C_ARCH_S390         = SCMP_ARCH_S390; | ||||
| const uint32_t C_ARCH_S390X        = SCMP_ARCH_S390X; | ||||
| const uint32_t C_ARCH_PARISC       = SCMP_ARCH_PARISC; | ||||
| const uint32_t C_ARCH_PARISC64     = SCMP_ARCH_PARISC64; | ||||
| const uint32_t C_ARCH_RISCV64      = SCMP_ARCH_RISCV64; | ||||
|  | ||||
| #ifndef SCMP_ACT_LOG | ||||
| #define SCMP_ACT_LOG 0x7ffc0000U | ||||
| #endif | ||||
|  | ||||
| #ifndef SCMP_ACT_KILL_PROCESS | ||||
| #define SCMP_ACT_KILL_PROCESS 0x80000000U | ||||
| #endif | ||||
|  | ||||
| #ifndef SCMP_ACT_KILL_THREAD | ||||
| #define SCMP_ACT_KILL_THREAD	0x00000000U | ||||
| #endif | ||||
|  | ||||
| #ifndef SCMP_ACT_NOTIFY | ||||
| #define SCMP_ACT_NOTIFY 0x7fc00000U | ||||
| #endif | ||||
|  | ||||
| const uint32_t C_ACT_KILL          = SCMP_ACT_KILL; | ||||
| const uint32_t C_ACT_KILL_PROCESS  = SCMP_ACT_KILL_PROCESS; | ||||
| const uint32_t C_ACT_KILL_THREAD   = SCMP_ACT_KILL_THREAD; | ||||
| const uint32_t C_ACT_TRAP          = SCMP_ACT_TRAP; | ||||
| const uint32_t C_ACT_ERRNO         = SCMP_ACT_ERRNO(0); | ||||
| const uint32_t C_ACT_TRACE         = SCMP_ACT_TRACE(0); | ||||
| const uint32_t C_ACT_LOG           = SCMP_ACT_LOG; | ||||
| const uint32_t C_ACT_ALLOW         = SCMP_ACT_ALLOW; | ||||
| const uint32_t C_ACT_NOTIFY        = SCMP_ACT_NOTIFY; | ||||
|  | ||||
| // The libseccomp SCMP_FLTATR_CTL_LOG member of the scmp_filter_attr enum was | ||||
| // added in v2.4.0 | ||||
| #if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4 | ||||
| #define SCMP_FLTATR_CTL_LOG _SCMP_FLTATR_MIN | ||||
| #endif | ||||
|  | ||||
| // The following SCMP_FLTATR_*  were added in libseccomp v2.5.0. | ||||
| #if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 5 | ||||
| #define SCMP_FLTATR_CTL_SSB      _SCMP_FLTATR_MIN | ||||
| #define SCMP_FLTATR_CTL_OPTIMIZE _SCMP_FLTATR_MIN | ||||
| #define SCMP_FLTATR_API_SYSRAWRC _SCMP_FLTATR_MIN | ||||
| #endif | ||||
|  | ||||
| const uint32_t C_ATTRIBUTE_DEFAULT  = (uint32_t)SCMP_FLTATR_ACT_DEFAULT; | ||||
| const uint32_t C_ATTRIBUTE_BADARCH  = (uint32_t)SCMP_FLTATR_ACT_BADARCH; | ||||
| const uint32_t C_ATTRIBUTE_NNP      = (uint32_t)SCMP_FLTATR_CTL_NNP; | ||||
| const uint32_t C_ATTRIBUTE_TSYNC    = (uint32_t)SCMP_FLTATR_CTL_TSYNC; | ||||
| const uint32_t C_ATTRIBUTE_LOG      = (uint32_t)SCMP_FLTATR_CTL_LOG; | ||||
| const uint32_t C_ATTRIBUTE_SSB      = (uint32_t)SCMP_FLTATR_CTL_SSB; | ||||
| const uint32_t C_ATTRIBUTE_OPTIMIZE = (uint32_t)SCMP_FLTATR_CTL_OPTIMIZE; | ||||
| const uint32_t C_ATTRIBUTE_SYSRAWRC = (uint32_t)SCMP_FLTATR_API_SYSRAWRC; | ||||
|  | ||||
| const int      C_CMP_NE            = (int)SCMP_CMP_NE; | ||||
| const int      C_CMP_LT            = (int)SCMP_CMP_LT; | ||||
| const int      C_CMP_LE            = (int)SCMP_CMP_LE; | ||||
| const int      C_CMP_EQ            = (int)SCMP_CMP_EQ; | ||||
| const int      C_CMP_GE            = (int)SCMP_CMP_GE; | ||||
| const int      C_CMP_GT            = (int)SCMP_CMP_GT; | ||||
| const int      C_CMP_MASKED_EQ     = (int)SCMP_CMP_MASKED_EQ; | ||||
|  | ||||
| const int      C_VERSION_MAJOR     = SCMP_VER_MAJOR; | ||||
| const int      C_VERSION_MINOR     = SCMP_VER_MINOR; | ||||
| const int      C_VERSION_MICRO     = SCMP_VER_MICRO; | ||||
|  | ||||
| #if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR >= 3 | ||||
| unsigned int get_major_version() | ||||
| { | ||||
|         return seccomp_version()->major; | ||||
| } | ||||
|  | ||||
| unsigned int get_minor_version() | ||||
| { | ||||
|         return seccomp_version()->minor; | ||||
| } | ||||
|  | ||||
| unsigned int get_micro_version() | ||||
| { | ||||
|         return seccomp_version()->micro; | ||||
| } | ||||
| #else | ||||
| unsigned int get_major_version() | ||||
| { | ||||
|         return (unsigned int)C_VERSION_MAJOR; | ||||
| } | ||||
|  | ||||
| unsigned int get_minor_version() | ||||
| { | ||||
|         return (unsigned int)C_VERSION_MINOR; | ||||
| } | ||||
|  | ||||
| unsigned int get_micro_version() | ||||
| { | ||||
|         return (unsigned int)C_VERSION_MICRO; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| // The libseccomp API level functions were added in v2.4.0 | ||||
| #if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4 | ||||
| const unsigned int seccomp_api_get(void) | ||||
| { | ||||
| 	// libseccomp-golang requires libseccomp v2.2.0, at a minimum, which | ||||
| 	// supported API level 2. However, the kernel may not support API level | ||||
| 	// 2 constructs which are the seccomp() system call and the TSYNC | ||||
| 	// filter flag. Return the "reserved" value of 0 here to indicate that | ||||
| 	// proper API level support is not available in libseccomp. | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int seccomp_api_set(unsigned int level) | ||||
| { | ||||
| 	return -EOPNOTSUPP; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| typedef struct scmp_arg_cmp* scmp_cast_t; | ||||
|  | ||||
| void* make_arg_cmp_array(unsigned int length) | ||||
| { | ||||
|         return calloc(length, sizeof(struct scmp_arg_cmp)); | ||||
| } | ||||
|  | ||||
| // Wrapper to add an scmp_arg_cmp struct to an existing arg_cmp array | ||||
| void add_struct_arg_cmp( | ||||
|                         struct scmp_arg_cmp* arr, | ||||
|                         unsigned int pos, | ||||
|                         unsigned int arg, | ||||
|                         int compare, | ||||
|                         uint64_t a, | ||||
|                         uint64_t b | ||||
|                        ) | ||||
| { | ||||
|         arr[pos].arg = arg; | ||||
|         arr[pos].op = compare; | ||||
|         arr[pos].datum_a = a; | ||||
|         arr[pos].datum_b = b; | ||||
|  | ||||
|         return; | ||||
| } | ||||
|  | ||||
| // The seccomp notify API functions were added in v2.5.0 | ||||
| #if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 5 | ||||
|  | ||||
| struct seccomp_data { | ||||
| 	int nr; | ||||
| 	__u32 arch; | ||||
| 	__u64 instruction_pointer; | ||||
| 	__u64 args[6]; | ||||
| }; | ||||
|  | ||||
| struct seccomp_notif { | ||||
| 	__u64 id; | ||||
| 	__u32 pid; | ||||
| 	__u32 flags; | ||||
| 	struct seccomp_data data; | ||||
| }; | ||||
|  | ||||
| struct seccomp_notif_resp { | ||||
| 	__u64 id; | ||||
| 	__s64 val; | ||||
| 	__s32 error; | ||||
| 	__u32 flags; | ||||
| }; | ||||
|  | ||||
| int seccomp_notify_alloc(struct seccomp_notif **req, struct seccomp_notif_resp **resp) { | ||||
| 	return -EOPNOTSUPP; | ||||
| } | ||||
| int seccomp_notify_fd(const scmp_filter_ctx ctx) { | ||||
| 	return -EOPNOTSUPP; | ||||
| } | ||||
| void seccomp_notify_free(struct seccomp_notif *req, struct seccomp_notif_resp *resp) { | ||||
| } | ||||
| int seccomp_notify_id_valid(int fd, uint64_t id) { | ||||
| 	return -EOPNOTSUPP; | ||||
| } | ||||
| int seccomp_notify_receive(int fd, struct seccomp_notif *req) { | ||||
| 	return -EOPNOTSUPP; | ||||
| } | ||||
| int seccomp_notify_respond(int fd, struct seccomp_notif_resp *resp) { | ||||
| 	return -EOPNOTSUPP; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| */ | ||||
| import "C" | ||||
|  | ||||
| // Nonexported types | ||||
| type scmpFilterAttr uint32 | ||||
|  | ||||
| // Nonexported constants | ||||
|  | ||||
| const ( | ||||
| 	filterAttrActDefault scmpFilterAttr = iota | ||||
| 	filterAttrActBadArch | ||||
| 	filterAttrNNP | ||||
| 	filterAttrTsync | ||||
| 	filterAttrLog | ||||
| 	filterAttrSSB | ||||
| 	filterAttrOptimize | ||||
| 	filterAttrRawRC | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	// An error return from certain libseccomp functions | ||||
| 	scmpError C.int = -1 | ||||
| 	// Comparison boundaries to check for architecture validity | ||||
| 	archStart ScmpArch = ArchNative | ||||
| 	archEnd   ScmpArch = ArchRISCV64 | ||||
| 	// Comparison boundaries to check for action validity | ||||
| 	actionStart ScmpAction = ActKillThread | ||||
| 	actionEnd   ScmpAction = ActKillProcess | ||||
| 	// Comparison boundaries to check for comparison operator validity | ||||
| 	compareOpStart ScmpCompareOp = CompareNotEqual | ||||
| 	compareOpEnd   ScmpCompareOp = CompareMaskedEqual | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// errBadFilter is thrown on bad filter context. | ||||
| 	errBadFilter = errors.New("filter is invalid or uninitialized") | ||||
| 	errDefAction = errors.New("requested action matches default action of filter") | ||||
| 	// Constants representing library major, minor, and micro versions | ||||
| 	verMajor = uint(C.get_major_version()) | ||||
| 	verMinor = uint(C.get_minor_version()) | ||||
| 	verMicro = uint(C.get_micro_version()) | ||||
| ) | ||||
|  | ||||
| // Nonexported functions | ||||
|  | ||||
| // checkVersion returns an error if the libseccomp version being used | ||||
| // is less than the one specified by major, minor, and micro arguments. | ||||
| // Argument op is an arbitrary non-empty operation description, which | ||||
| // is used as a part of the error message returned. | ||||
| // | ||||
| // Most users should use checkAPI instead. | ||||
| func checkVersion(op string, major, minor, micro uint) error { | ||||
| 	if (verMajor > major) || | ||||
| 		(verMajor == major && verMinor > minor) || | ||||
| 		(verMajor == major && verMinor == minor && verMicro >= micro) { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return &VersionError{ | ||||
| 		op:    op, | ||||
| 		major: major, | ||||
| 		minor: minor, | ||||
| 		micro: micro, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func ensureSupportedVersion() error { | ||||
| 	return checkVersion("seccomp", 2, 3, 1) | ||||
| } | ||||
|  | ||||
| // Get the API level | ||||
| func getAPI() (uint, error) { | ||||
| 	api := C.seccomp_api_get() | ||||
| 	if api == 0 { | ||||
| 		return 0, errors.New("API level operations are not supported") | ||||
| 	} | ||||
|  | ||||
| 	return uint(api), nil | ||||
| } | ||||
|  | ||||
| // Set the API level | ||||
| func setAPI(api uint) error { | ||||
| 	if retCode := C.seccomp_api_set(C.uint(api)); retCode != 0 { | ||||
| 		e := errRc(retCode) | ||||
| 		if e == syscall.EOPNOTSUPP { | ||||
| 			return errors.New("API level operations are not supported") | ||||
| 		} | ||||
|  | ||||
| 		return fmt.Errorf("could not set API level: %w", e) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Filter helpers | ||||
|  | ||||
| // Filter finalizer - ensure that kernel context for filters is freed | ||||
| func filterFinalizer(f *ScmpFilter) { | ||||
| 	f.Release() | ||||
| } | ||||
|  | ||||
| func errRc(rc C.int) error { | ||||
| 	return syscall.Errno(-1 * rc) | ||||
| } | ||||
|  | ||||
| // Get a raw filter attribute | ||||
| func (f *ScmpFilter) getFilterAttr(attr scmpFilterAttr) (C.uint32_t, error) { | ||||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
|  | ||||
| 	if !f.valid { | ||||
| 		return 0x0, errBadFilter | ||||
| 	} | ||||
|  | ||||
| 	var attribute C.uint32_t | ||||
|  | ||||
| 	retCode := C.seccomp_attr_get(f.filterCtx, attr.toNative(), &attribute) | ||||
| 	if retCode != 0 { | ||||
| 		return 0x0, errRc(retCode) | ||||
| 	} | ||||
|  | ||||
| 	return attribute, nil | ||||
| } | ||||
|  | ||||
| // Set a raw filter attribute | ||||
| func (f *ScmpFilter) setFilterAttr(attr scmpFilterAttr, value C.uint32_t) error { | ||||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
|  | ||||
| 	if !f.valid { | ||||
| 		return errBadFilter | ||||
| 	} | ||||
|  | ||||
| 	retCode := C.seccomp_attr_set(f.filterCtx, attr.toNative(), value) | ||||
| 	if retCode != 0 { | ||||
| 		return errRc(retCode) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // DOES NOT LOCK OR CHECK VALIDITY | ||||
| // Assumes caller has already done this | ||||
| // Wrapper for seccomp_rule_add_... functions | ||||
| func (f *ScmpFilter) addRuleWrapper(call ScmpSyscall, action ScmpAction, exact bool, length C.uint, cond C.scmp_cast_t) error { | ||||
| 	if length != 0 && cond == nil { | ||||
| 		return errors.New("null conditions list, but length is nonzero") | ||||
| 	} | ||||
|  | ||||
| 	var retCode C.int | ||||
| 	if exact { | ||||
| 		retCode = C.seccomp_rule_add_exact_array(f.filterCtx, action.toNative(), C.int(call), length, cond) | ||||
| 	} else { | ||||
| 		retCode = C.seccomp_rule_add_array(f.filterCtx, action.toNative(), C.int(call), length, cond) | ||||
| 	} | ||||
|  | ||||
| 	if retCode != 0 { | ||||
| 		switch e := errRc(retCode); e { | ||||
| 		case syscall.EFAULT: | ||||
| 			return fmt.Errorf("unrecognized syscall %#x", int32(call)) | ||||
| 		// libseccomp >= v2.5.0 returns EACCES, older versions return EPERM. | ||||
| 		// TODO: remove EPERM once libseccomp < v2.5.0 is not supported. | ||||
| 		case syscall.EPERM, syscall.EACCES: | ||||
| 			return errDefAction | ||||
| 		case syscall.EINVAL: | ||||
| 			return errors.New("two checks on same syscall argument") | ||||
| 		default: | ||||
| 			return e | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Generic add function for filter rules | ||||
| func (f *ScmpFilter) addRuleGeneric(call ScmpSyscall, action ScmpAction, exact bool, conds []ScmpCondition) error { | ||||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
|  | ||||
| 	if !f.valid { | ||||
| 		return errBadFilter | ||||
| 	} | ||||
|  | ||||
| 	if len(conds) == 0 { | ||||
| 		if err := f.addRuleWrapper(call, action, exact, 0, nil); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} else { | ||||
| 		argsArr := C.make_arg_cmp_array(C.uint(len(conds))) | ||||
| 		if argsArr == nil { | ||||
| 			return errors.New("error allocating memory for conditions") | ||||
| 		} | ||||
| 		defer C.free(argsArr) | ||||
|  | ||||
| 		for i, cond := range conds { | ||||
| 			C.add_struct_arg_cmp(C.scmp_cast_t(argsArr), C.uint(i), | ||||
| 				C.uint(cond.Argument), cond.Op.toNative(), | ||||
| 				C.uint64_t(cond.Operand1), C.uint64_t(cond.Operand2)) | ||||
| 		} | ||||
|  | ||||
| 		if err := f.addRuleWrapper(call, action, exact, C.uint(len(conds)), C.scmp_cast_t(argsArr)); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Generic Helpers | ||||
|  | ||||
| // Helper - Sanitize Arch token input | ||||
| func sanitizeArch(in ScmpArch) error { | ||||
| 	if in < archStart || in > archEnd { | ||||
| 		return fmt.Errorf("unrecognized architecture %#x", uint(in)) | ||||
| 	} | ||||
|  | ||||
| 	if in.toNative() == C.C_ARCH_BAD { | ||||
| 		return fmt.Errorf("architecture %v is not supported on this version of the library", in) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func sanitizeAction(in ScmpAction) error { | ||||
| 	inTmp := in & 0x0000FFFF | ||||
| 	if inTmp < actionStart || inTmp > actionEnd { | ||||
| 		return fmt.Errorf("unrecognized action %#x", uint(inTmp)) | ||||
| 	} | ||||
|  | ||||
| 	if inTmp != ActTrace && inTmp != ActErrno && (in&0xFFFF0000) != 0 { | ||||
| 		return errors.New("highest 16 bits must be zeroed except for Trace and Errno") | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func sanitizeCompareOp(in ScmpCompareOp) error { | ||||
| 	if in < compareOpStart || in > compareOpEnd { | ||||
| 		return fmt.Errorf("unrecognized comparison operator %#x", uint(in)) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func archFromNative(a C.uint32_t) (ScmpArch, error) { | ||||
| 	switch a { | ||||
| 	case C.C_ARCH_X86: | ||||
| 		return ArchX86, nil | ||||
| 	case C.C_ARCH_X86_64: | ||||
| 		return ArchAMD64, nil | ||||
| 	case C.C_ARCH_X32: | ||||
| 		return ArchX32, nil | ||||
| 	case C.C_ARCH_ARM: | ||||
| 		return ArchARM, nil | ||||
| 	case C.C_ARCH_NATIVE: | ||||
| 		return ArchNative, nil | ||||
| 	case C.C_ARCH_AARCH64: | ||||
| 		return ArchARM64, nil | ||||
| 	case C.C_ARCH_MIPS: | ||||
| 		return ArchMIPS, nil | ||||
| 	case C.C_ARCH_MIPS64: | ||||
| 		return ArchMIPS64, nil | ||||
| 	case C.C_ARCH_MIPS64N32: | ||||
| 		return ArchMIPS64N32, nil | ||||
| 	case C.C_ARCH_MIPSEL: | ||||
| 		return ArchMIPSEL, nil | ||||
| 	case C.C_ARCH_MIPSEL64: | ||||
| 		return ArchMIPSEL64, nil | ||||
| 	case C.C_ARCH_MIPSEL64N32: | ||||
| 		return ArchMIPSEL64N32, nil | ||||
| 	case C.C_ARCH_PPC: | ||||
| 		return ArchPPC, nil | ||||
| 	case C.C_ARCH_PPC64: | ||||
| 		return ArchPPC64, nil | ||||
| 	case C.C_ARCH_PPC64LE: | ||||
| 		return ArchPPC64LE, nil | ||||
| 	case C.C_ARCH_S390: | ||||
| 		return ArchS390, nil | ||||
| 	case C.C_ARCH_S390X: | ||||
| 		return ArchS390X, nil | ||||
| 	case C.C_ARCH_PARISC: | ||||
| 		return ArchPARISC, nil | ||||
| 	case C.C_ARCH_PARISC64: | ||||
| 		return ArchPARISC64, nil | ||||
| 	case C.C_ARCH_RISCV64: | ||||
| 		return ArchRISCV64, nil | ||||
| 	default: | ||||
| 		return 0x0, fmt.Errorf("unrecognized architecture %#x", uint32(a)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Only use with sanitized arches, no error handling | ||||
| func (a ScmpArch) toNative() C.uint32_t { | ||||
| 	switch a { | ||||
| 	case ArchX86: | ||||
| 		return C.C_ARCH_X86 | ||||
| 	case ArchAMD64: | ||||
| 		return C.C_ARCH_X86_64 | ||||
| 	case ArchX32: | ||||
| 		return C.C_ARCH_X32 | ||||
| 	case ArchARM: | ||||
| 		return C.C_ARCH_ARM | ||||
| 	case ArchARM64: | ||||
| 		return C.C_ARCH_AARCH64 | ||||
| 	case ArchMIPS: | ||||
| 		return C.C_ARCH_MIPS | ||||
| 	case ArchMIPS64: | ||||
| 		return C.C_ARCH_MIPS64 | ||||
| 	case ArchMIPS64N32: | ||||
| 		return C.C_ARCH_MIPS64N32 | ||||
| 	case ArchMIPSEL: | ||||
| 		return C.C_ARCH_MIPSEL | ||||
| 	case ArchMIPSEL64: | ||||
| 		return C.C_ARCH_MIPSEL64 | ||||
| 	case ArchMIPSEL64N32: | ||||
| 		return C.C_ARCH_MIPSEL64N32 | ||||
| 	case ArchPPC: | ||||
| 		return C.C_ARCH_PPC | ||||
| 	case ArchPPC64: | ||||
| 		return C.C_ARCH_PPC64 | ||||
| 	case ArchPPC64LE: | ||||
| 		return C.C_ARCH_PPC64LE | ||||
| 	case ArchS390: | ||||
| 		return C.C_ARCH_S390 | ||||
| 	case ArchS390X: | ||||
| 		return C.C_ARCH_S390X | ||||
| 	case ArchPARISC: | ||||
| 		return C.C_ARCH_PARISC | ||||
| 	case ArchPARISC64: | ||||
| 		return C.C_ARCH_PARISC64 | ||||
| 	case ArchRISCV64: | ||||
| 		return C.C_ARCH_RISCV64 | ||||
| 	case ArchNative: | ||||
| 		return C.C_ARCH_NATIVE | ||||
| 	default: | ||||
| 		return 0x0 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Only use with sanitized ops, no error handling | ||||
| func (a ScmpCompareOp) toNative() C.int { | ||||
| 	switch a { | ||||
| 	case CompareNotEqual: | ||||
| 		return C.C_CMP_NE | ||||
| 	case CompareLess: | ||||
| 		return C.C_CMP_LT | ||||
| 	case CompareLessOrEqual: | ||||
| 		return C.C_CMP_LE | ||||
| 	case CompareEqual: | ||||
| 		return C.C_CMP_EQ | ||||
| 	case CompareGreaterEqual: | ||||
| 		return C.C_CMP_GE | ||||
| 	case CompareGreater: | ||||
| 		return C.C_CMP_GT | ||||
| 	case CompareMaskedEqual: | ||||
| 		return C.C_CMP_MASKED_EQ | ||||
| 	default: | ||||
| 		return 0x0 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func actionFromNative(a C.uint32_t) (ScmpAction, error) { | ||||
| 	aTmp := a & 0xFFFF | ||||
| 	switch a & 0xFFFF0000 { | ||||
| 	case C.C_ACT_KILL_PROCESS: | ||||
| 		return ActKillProcess, nil | ||||
| 	case C.C_ACT_KILL_THREAD: | ||||
| 		return ActKillThread, nil | ||||
| 	case C.C_ACT_TRAP: | ||||
| 		return ActTrap, nil | ||||
| 	case C.C_ACT_ERRNO: | ||||
| 		return ActErrno.SetReturnCode(int16(aTmp)), nil | ||||
| 	case C.C_ACT_TRACE: | ||||
| 		return ActTrace.SetReturnCode(int16(aTmp)), nil | ||||
| 	case C.C_ACT_LOG: | ||||
| 		return ActLog, nil | ||||
| 	case C.C_ACT_ALLOW: | ||||
| 		return ActAllow, nil | ||||
| 	case C.C_ACT_NOTIFY: | ||||
| 		return ActNotify, nil | ||||
| 	default: | ||||
| 		return 0x0, fmt.Errorf("unrecognized action %#x", uint32(a)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Only use with sanitized actions, no error handling | ||||
| func (a ScmpAction) toNative() C.uint32_t { | ||||
| 	switch a & 0xFFFF { | ||||
| 	case ActKillProcess: | ||||
| 		return C.C_ACT_KILL_PROCESS | ||||
| 	case ActKillThread: | ||||
| 		return C.C_ACT_KILL_THREAD | ||||
| 	case ActTrap: | ||||
| 		return C.C_ACT_TRAP | ||||
| 	case ActErrno: | ||||
| 		return C.C_ACT_ERRNO | (C.uint32_t(a) >> 16) | ||||
| 	case ActTrace: | ||||
| 		return C.C_ACT_TRACE | (C.uint32_t(a) >> 16) | ||||
| 	case ActLog: | ||||
| 		return C.C_ACT_LOG | ||||
| 	case ActAllow: | ||||
| 		return C.C_ACT_ALLOW | ||||
| 	case ActNotify: | ||||
| 		return C.C_ACT_NOTIFY | ||||
| 	default: | ||||
| 		return 0x0 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Internal only, assumes safe attribute | ||||
| func (a scmpFilterAttr) toNative() uint32 { | ||||
| 	switch a { | ||||
| 	case filterAttrActDefault: | ||||
| 		return uint32(C.C_ATTRIBUTE_DEFAULT) | ||||
| 	case filterAttrActBadArch: | ||||
| 		return uint32(C.C_ATTRIBUTE_BADARCH) | ||||
| 	case filterAttrNNP: | ||||
| 		return uint32(C.C_ATTRIBUTE_NNP) | ||||
| 	case filterAttrTsync: | ||||
| 		return uint32(C.C_ATTRIBUTE_TSYNC) | ||||
| 	case filterAttrLog: | ||||
| 		return uint32(C.C_ATTRIBUTE_LOG) | ||||
| 	case filterAttrSSB: | ||||
| 		return uint32(C.C_ATTRIBUTE_SSB) | ||||
| 	case filterAttrOptimize: | ||||
| 		return uint32(C.C_ATTRIBUTE_OPTIMIZE) | ||||
| 	case filterAttrRawRC: | ||||
| 		return uint32(C.C_ATTRIBUTE_SYSRAWRC) | ||||
| 	default: | ||||
| 		return 0x0 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func syscallFromNative(a C.int) ScmpSyscall { | ||||
| 	return ScmpSyscall(a) | ||||
| } | ||||
|  | ||||
| func notifReqFromNative(req *C.struct_seccomp_notif) (*ScmpNotifReq, error) { | ||||
| 	scmpArgs := make([]uint64, 6) | ||||
| 	for i := 0; i < len(scmpArgs); i++ { | ||||
| 		scmpArgs[i] = uint64(req.data.args[i]) | ||||
| 	} | ||||
|  | ||||
| 	arch, err := archFromNative(req.data.arch) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	scmpData := ScmpNotifData{ | ||||
| 		Syscall:      syscallFromNative(req.data.nr), | ||||
| 		Arch:         arch, | ||||
| 		InstrPointer: uint64(req.data.instruction_pointer), | ||||
| 		Args:         scmpArgs, | ||||
| 	} | ||||
|  | ||||
| 	scmpReq := &ScmpNotifReq{ | ||||
| 		ID:    uint64(req.id), | ||||
| 		Pid:   uint32(req.pid), | ||||
| 		Flags: uint32(req.flags), | ||||
| 		Data:  scmpData, | ||||
| 	} | ||||
|  | ||||
| 	return scmpReq, nil | ||||
| } | ||||
|  | ||||
| func (scmpResp *ScmpNotifResp) toNative(resp *C.struct_seccomp_notif_resp) { | ||||
| 	resp.id = C.__u64(scmpResp.ID) | ||||
| 	resp.val = C.__s64(scmpResp.Val) | ||||
| 	resp.error = (C.__s32(scmpResp.Error) * -1) // kernel requires a negated value | ||||
| 	resp.flags = C.__u32(scmpResp.Flags) | ||||
| } | ||||
|  | ||||
| // checkAPI checks that both the API level and the seccomp version is equal to | ||||
| // or greater than the specified minLevel and major, minor, micro, | ||||
| // respectively, and returns an error otherwise. Argument op is an arbitrary | ||||
| // non-empty operation description, used as a part of the error message | ||||
| // returned. | ||||
| func checkAPI(op string, minLevel uint, major, minor, micro uint) error { | ||||
| 	// Ignore error from getAPI, as it returns level == 0 in case of error. | ||||
| 	level, _ := getAPI() | ||||
| 	if level >= minLevel { | ||||
| 		return checkVersion(op, major, minor, micro) | ||||
| 	} | ||||
| 	return &VersionError{ | ||||
| 		op:     op, | ||||
| 		curAPI: level, | ||||
| 		minAPI: minLevel, | ||||
| 		major:  major, | ||||
| 		minor:  minor, | ||||
| 		micro:  micro, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Userspace Notification API | ||||
| // Calls to C.seccomp_notify* hidden from seccomp.go | ||||
|  | ||||
| func notifSupported() error { | ||||
| 	return checkAPI("seccomp notification", 6, 2, 5, 0) | ||||
| } | ||||
|  | ||||
| func (f *ScmpFilter) getNotifFd() (ScmpFd, error) { | ||||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
|  | ||||
| 	if !f.valid { | ||||
| 		return -1, errBadFilter | ||||
| 	} | ||||
| 	if err := notifSupported(); err != nil { | ||||
| 		return -1, err | ||||
| 	} | ||||
|  | ||||
| 	fd := C.seccomp_notify_fd(f.filterCtx) | ||||
|  | ||||
| 	return ScmpFd(fd), nil | ||||
| } | ||||
|  | ||||
| func notifReceive(fd ScmpFd) (*ScmpNotifReq, error) { | ||||
| 	var req *C.struct_seccomp_notif | ||||
| 	var resp *C.struct_seccomp_notif_resp | ||||
|  | ||||
| 	if err := notifSupported(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// we only use the request here; the response is unused | ||||
| 	if retCode := C.seccomp_notify_alloc(&req, &resp); retCode != 0 { | ||||
| 		return nil, errRc(retCode) | ||||
| 	} | ||||
|  | ||||
| 	defer func() { | ||||
| 		C.seccomp_notify_free(req, resp) | ||||
| 	}() | ||||
|  | ||||
| 	for { | ||||
| 		retCode, errno := C.seccomp_notify_receive(C.int(fd), req) | ||||
| 		if retCode == 0 { | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
| 		if errno == syscall.EINTR { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if errno == syscall.ENOENT { | ||||
| 			return nil, errno | ||||
| 		} | ||||
|  | ||||
| 		return nil, errRc(retCode) | ||||
| 	} | ||||
|  | ||||
| 	return notifReqFromNative(req) | ||||
| } | ||||
|  | ||||
| func notifRespond(fd ScmpFd, scmpResp *ScmpNotifResp) error { | ||||
| 	var req *C.struct_seccomp_notif | ||||
| 	var resp *C.struct_seccomp_notif_resp | ||||
|  | ||||
| 	if err := notifSupported(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// we only use the response here; the request is discarded | ||||
| 	if retCode := C.seccomp_notify_alloc(&req, &resp); retCode != 0 { | ||||
| 		return errRc(retCode) | ||||
| 	} | ||||
|  | ||||
| 	defer func() { | ||||
| 		C.seccomp_notify_free(req, resp) | ||||
| 	}() | ||||
|  | ||||
| 	scmpResp.toNative(resp) | ||||
|  | ||||
| 	for { | ||||
| 		retCode, errno := C.seccomp_notify_respond(C.int(fd), resp) | ||||
| 		if retCode == 0 { | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
| 		if errno == syscall.EINTR { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if errno == syscall.ENOENT { | ||||
| 			return errno | ||||
| 		} | ||||
|  | ||||
| 		return errRc(retCode) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func notifIDValid(fd ScmpFd, id uint64) error { | ||||
| 	if err := notifSupported(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for { | ||||
| 		retCode, errno := C.seccomp_notify_id_valid(C.int(fd), C.uint64_t(id)) | ||||
| 		if retCode == 0 { | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
| 		if errno == syscall.EINTR { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if errno == syscall.ENOENT { | ||||
| 			return errno | ||||
| 		} | ||||
|  | ||||
| 		return errRc(retCode) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										24
									
								
								vendor/github.com/syndtr/gocapability/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/syndtr/gocapability/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,24 +0,0 @@ | ||||
| Copyright 2013 Suryandaru Triandana <syndtr@gmail.com> | ||||
| All rights reserved. | ||||
|  | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions are | ||||
| met: | ||||
|  | ||||
|     * Redistributions of source code must retain the above copyright | ||||
| notice, this list of conditions and the following disclaimer. | ||||
|     * Redistributions in binary form must reproduce the above copyright | ||||
| notice, this list of conditions and the following disclaimer in the | ||||
| documentation and/or other materials provided with the distribution. | ||||
|  | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
| HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||
| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
							
								
								
									
										133
									
								
								vendor/github.com/syndtr/gocapability/capability/capability.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										133
									
								
								vendor/github.com/syndtr/gocapability/capability/capability.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,133 +0,0 @@ | ||||
| // Copyright (c) 2013, Suryandaru Triandana <syndtr@gmail.com> | ||||
| // All rights reserved. | ||||
| // | ||||
| // Use of this source code is governed by a BSD-style license that can be | ||||
| // found in the LICENSE file. | ||||
|  | ||||
| // Package capability provides utilities for manipulating POSIX capabilities. | ||||
| package capability | ||||
|  | ||||
| type Capabilities interface { | ||||
| 	// Get check whether a capability present in the given | ||||
| 	// capabilities set. The 'which' value should be one of EFFECTIVE, | ||||
| 	// PERMITTED, INHERITABLE, BOUNDING or AMBIENT. | ||||
| 	Get(which CapType, what Cap) bool | ||||
|  | ||||
| 	// Empty check whether all capability bits of the given capabilities | ||||
| 	// set are zero. The 'which' value should be one of EFFECTIVE, | ||||
| 	// PERMITTED, INHERITABLE, BOUNDING or AMBIENT. | ||||
| 	Empty(which CapType) bool | ||||
|  | ||||
| 	// Full check whether all capability bits of the given capabilities | ||||
| 	// set are one. The 'which' value should be one of EFFECTIVE, | ||||
| 	// PERMITTED, INHERITABLE, BOUNDING or AMBIENT. | ||||
| 	Full(which CapType) bool | ||||
|  | ||||
| 	// Set sets capabilities of the given capabilities sets. The | ||||
| 	// 'which' value should be one or combination (OR'ed) of EFFECTIVE, | ||||
| 	// PERMITTED, INHERITABLE, BOUNDING or AMBIENT. | ||||
| 	Set(which CapType, caps ...Cap) | ||||
|  | ||||
| 	// Unset unsets capabilities of the given capabilities sets. The | ||||
| 	// 'which' value should be one or combination (OR'ed) of EFFECTIVE, | ||||
| 	// PERMITTED, INHERITABLE, BOUNDING or AMBIENT. | ||||
| 	Unset(which CapType, caps ...Cap) | ||||
|  | ||||
| 	// Fill sets all bits of the given capabilities kind to one. The | ||||
| 	// 'kind' value should be one or combination (OR'ed) of CAPS, | ||||
| 	// BOUNDS or AMBS. | ||||
| 	Fill(kind CapType) | ||||
|  | ||||
| 	// Clear sets all bits of the given capabilities kind to zero. The | ||||
| 	// 'kind' value should be one or combination (OR'ed) of CAPS, | ||||
| 	// BOUNDS or AMBS. | ||||
| 	Clear(kind CapType) | ||||
|  | ||||
| 	// String return current capabilities state of the given capabilities | ||||
| 	// set as string. The 'which' value should be one of EFFECTIVE, | ||||
| 	// PERMITTED, INHERITABLE BOUNDING or AMBIENT | ||||
| 	StringCap(which CapType) string | ||||
|  | ||||
| 	// String return current capabilities state as string. | ||||
| 	String() string | ||||
|  | ||||
| 	// Load load actual capabilities value. This will overwrite all | ||||
| 	// outstanding changes. | ||||
| 	Load() error | ||||
|  | ||||
| 	// Apply apply the capabilities settings, so all changes will take | ||||
| 	// effect. | ||||
| 	Apply(kind CapType) error | ||||
| } | ||||
|  | ||||
| // NewPid initializes a new Capabilities object for given pid when | ||||
| // it is nonzero, or for the current process if pid is 0. | ||||
| // | ||||
| // Deprecated: Replace with NewPid2.  For example, replace: | ||||
| // | ||||
| //    c, err := NewPid(0) | ||||
| //    if err != nil { | ||||
| //      return err | ||||
| //    } | ||||
| // | ||||
| // with: | ||||
| // | ||||
| //    c, err := NewPid2(0) | ||||
| //    if err != nil { | ||||
| //      return err | ||||
| //    } | ||||
| //    err = c.Load() | ||||
| //    if err != nil { | ||||
| //      return err | ||||
| //    } | ||||
| func NewPid(pid int) (Capabilities, error) { | ||||
| 	c, err := newPid(pid) | ||||
| 	if err != nil { | ||||
| 		return c, err | ||||
| 	} | ||||
| 	err = c.Load() | ||||
| 	return c, err | ||||
| } | ||||
|  | ||||
| // NewPid2 initializes a new Capabilities object for given pid when | ||||
| // it is nonzero, or for the current process if pid is 0.  This | ||||
| // does not load the process's current capabilities; to do that you | ||||
| // must call Load explicitly. | ||||
| func NewPid2(pid int) (Capabilities, error) { | ||||
| 	return newPid(pid) | ||||
| } | ||||
|  | ||||
| // NewFile initializes a new Capabilities object for given file path. | ||||
| // | ||||
| // Deprecated: Replace with NewFile2.  For example, replace: | ||||
| // | ||||
| //    c, err := NewFile(path) | ||||
| //    if err != nil { | ||||
| //      return err | ||||
| //    } | ||||
| // | ||||
| // with: | ||||
| // | ||||
| //    c, err := NewFile2(path) | ||||
| //    if err != nil { | ||||
| //      return err | ||||
| //    } | ||||
| //    err = c.Load() | ||||
| //    if err != nil { | ||||
| //      return err | ||||
| //    } | ||||
| func NewFile(path string) (Capabilities, error) { | ||||
| 	c, err := newFile(path) | ||||
| 	if err != nil { | ||||
| 		return c, err | ||||
| 	} | ||||
| 	err = c.Load() | ||||
| 	return c, err | ||||
| } | ||||
|  | ||||
| // NewFile2 creates a new initialized Capabilities object for given | ||||
| // file path.  This does not load the process's current capabilities; | ||||
| // to do that you must call Load explicitly. | ||||
| func NewFile2(path string) (Capabilities, error) { | ||||
| 	return newFile(path) | ||||
| } | ||||
							
								
								
									
										642
									
								
								vendor/github.com/syndtr/gocapability/capability/capability_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										642
									
								
								vendor/github.com/syndtr/gocapability/capability/capability_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,642 +0,0 @@ | ||||
| // Copyright (c) 2013, Suryandaru Triandana <syndtr@gmail.com> | ||||
| // All rights reserved. | ||||
| // | ||||
| // Use of this source code is governed by a BSD-style license that can be | ||||
| // found in the LICENSE file. | ||||
|  | ||||
| package capability | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
| ) | ||||
|  | ||||
| var errUnknownVers = errors.New("unknown capability version") | ||||
|  | ||||
| const ( | ||||
| 	linuxCapVer1 = 0x19980330 | ||||
| 	linuxCapVer2 = 0x20071026 | ||||
| 	linuxCapVer3 = 0x20080522 | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	capVers    uint32 | ||||
| 	capLastCap Cap | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	var hdr capHeader | ||||
| 	capget(&hdr, nil) | ||||
| 	capVers = hdr.version | ||||
|  | ||||
| 	if initLastCap() == nil { | ||||
| 		CAP_LAST_CAP = capLastCap | ||||
| 		if capLastCap > 31 { | ||||
| 			capUpperMask = (uint32(1) << (uint(capLastCap) - 31)) - 1 | ||||
| 		} else { | ||||
| 			capUpperMask = 0 | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func initLastCap() error { | ||||
| 	if capLastCap != 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	f, err := os.Open("/proc/sys/kernel/cap_last_cap") | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer f.Close() | ||||
|  | ||||
| 	var b []byte = make([]byte, 11) | ||||
| 	_, err = f.Read(b) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	fmt.Sscanf(string(b), "%d", &capLastCap) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func mkStringCap(c Capabilities, which CapType) (ret string) { | ||||
| 	for i, first := Cap(0), true; i <= CAP_LAST_CAP; i++ { | ||||
| 		if !c.Get(which, i) { | ||||
| 			continue | ||||
| 		} | ||||
| 		if first { | ||||
| 			first = false | ||||
| 		} else { | ||||
| 			ret += ", " | ||||
| 		} | ||||
| 		ret += i.String() | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func mkString(c Capabilities, max CapType) (ret string) { | ||||
| 	ret = "{" | ||||
| 	for i := CapType(1); i <= max; i <<= 1 { | ||||
| 		ret += " " + i.String() + "=\"" | ||||
| 		if c.Empty(i) { | ||||
| 			ret += "empty" | ||||
| 		} else if c.Full(i) { | ||||
| 			ret += "full" | ||||
| 		} else { | ||||
| 			ret += c.StringCap(i) | ||||
| 		} | ||||
| 		ret += "\"" | ||||
| 	} | ||||
| 	ret += " }" | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func newPid(pid int) (c Capabilities, err error) { | ||||
| 	switch capVers { | ||||
| 	case linuxCapVer1: | ||||
| 		p := new(capsV1) | ||||
| 		p.hdr.version = capVers | ||||
| 		p.hdr.pid = int32(pid) | ||||
| 		c = p | ||||
| 	case linuxCapVer2, linuxCapVer3: | ||||
| 		p := new(capsV3) | ||||
| 		p.hdr.version = capVers | ||||
| 		p.hdr.pid = int32(pid) | ||||
| 		c = p | ||||
| 	default: | ||||
| 		err = errUnknownVers | ||||
| 		return | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| type capsV1 struct { | ||||
| 	hdr  capHeader | ||||
| 	data capData | ||||
| } | ||||
|  | ||||
| func (c *capsV1) Get(which CapType, what Cap) bool { | ||||
| 	if what > 32 { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	switch which { | ||||
| 	case EFFECTIVE: | ||||
| 		return (1<<uint(what))&c.data.effective != 0 | ||||
| 	case PERMITTED: | ||||
| 		return (1<<uint(what))&c.data.permitted != 0 | ||||
| 	case INHERITABLE: | ||||
| 		return (1<<uint(what))&c.data.inheritable != 0 | ||||
| 	} | ||||
|  | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func (c *capsV1) getData(which CapType) (ret uint32) { | ||||
| 	switch which { | ||||
| 	case EFFECTIVE: | ||||
| 		ret = c.data.effective | ||||
| 	case PERMITTED: | ||||
| 		ret = c.data.permitted | ||||
| 	case INHERITABLE: | ||||
| 		ret = c.data.inheritable | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (c *capsV1) Empty(which CapType) bool { | ||||
| 	return c.getData(which) == 0 | ||||
| } | ||||
|  | ||||
| func (c *capsV1) Full(which CapType) bool { | ||||
| 	return (c.getData(which) & 0x7fffffff) == 0x7fffffff | ||||
| } | ||||
|  | ||||
| func (c *capsV1) Set(which CapType, caps ...Cap) { | ||||
| 	for _, what := range caps { | ||||
| 		if what > 32 { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if which&EFFECTIVE != 0 { | ||||
| 			c.data.effective |= 1 << uint(what) | ||||
| 		} | ||||
| 		if which&PERMITTED != 0 { | ||||
| 			c.data.permitted |= 1 << uint(what) | ||||
| 		} | ||||
| 		if which&INHERITABLE != 0 { | ||||
| 			c.data.inheritable |= 1 << uint(what) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *capsV1) Unset(which CapType, caps ...Cap) { | ||||
| 	for _, what := range caps { | ||||
| 		if what > 32 { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if which&EFFECTIVE != 0 { | ||||
| 			c.data.effective &= ^(1 << uint(what)) | ||||
| 		} | ||||
| 		if which&PERMITTED != 0 { | ||||
| 			c.data.permitted &= ^(1 << uint(what)) | ||||
| 		} | ||||
| 		if which&INHERITABLE != 0 { | ||||
| 			c.data.inheritable &= ^(1 << uint(what)) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *capsV1) Fill(kind CapType) { | ||||
| 	if kind&CAPS == CAPS { | ||||
| 		c.data.effective = 0x7fffffff | ||||
| 		c.data.permitted = 0x7fffffff | ||||
| 		c.data.inheritable = 0 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *capsV1) Clear(kind CapType) { | ||||
| 	if kind&CAPS == CAPS { | ||||
| 		c.data.effective = 0 | ||||
| 		c.data.permitted = 0 | ||||
| 		c.data.inheritable = 0 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *capsV1) StringCap(which CapType) (ret string) { | ||||
| 	return mkStringCap(c, which) | ||||
| } | ||||
|  | ||||
| func (c *capsV1) String() (ret string) { | ||||
| 	return mkString(c, BOUNDING) | ||||
| } | ||||
|  | ||||
| func (c *capsV1) Load() (err error) { | ||||
| 	return capget(&c.hdr, &c.data) | ||||
| } | ||||
|  | ||||
| func (c *capsV1) Apply(kind CapType) error { | ||||
| 	if kind&CAPS == CAPS { | ||||
| 		return capset(&c.hdr, &c.data) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type capsV3 struct { | ||||
| 	hdr     capHeader | ||||
| 	data    [2]capData | ||||
| 	bounds  [2]uint32 | ||||
| 	ambient [2]uint32 | ||||
| } | ||||
|  | ||||
| func (c *capsV3) Get(which CapType, what Cap) bool { | ||||
| 	var i uint | ||||
| 	if what > 31 { | ||||
| 		i = uint(what) >> 5 | ||||
| 		what %= 32 | ||||
| 	} | ||||
|  | ||||
| 	switch which { | ||||
| 	case EFFECTIVE: | ||||
| 		return (1<<uint(what))&c.data[i].effective != 0 | ||||
| 	case PERMITTED: | ||||
| 		return (1<<uint(what))&c.data[i].permitted != 0 | ||||
| 	case INHERITABLE: | ||||
| 		return (1<<uint(what))&c.data[i].inheritable != 0 | ||||
| 	case BOUNDING: | ||||
| 		return (1<<uint(what))&c.bounds[i] != 0 | ||||
| 	case AMBIENT: | ||||
| 		return (1<<uint(what))&c.ambient[i] != 0 | ||||
| 	} | ||||
|  | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func (c *capsV3) getData(which CapType, dest []uint32) { | ||||
| 	switch which { | ||||
| 	case EFFECTIVE: | ||||
| 		dest[0] = c.data[0].effective | ||||
| 		dest[1] = c.data[1].effective | ||||
| 	case PERMITTED: | ||||
| 		dest[0] = c.data[0].permitted | ||||
| 		dest[1] = c.data[1].permitted | ||||
| 	case INHERITABLE: | ||||
| 		dest[0] = c.data[0].inheritable | ||||
| 		dest[1] = c.data[1].inheritable | ||||
| 	case BOUNDING: | ||||
| 		dest[0] = c.bounds[0] | ||||
| 		dest[1] = c.bounds[1] | ||||
| 	case AMBIENT: | ||||
| 		dest[0] = c.ambient[0] | ||||
| 		dest[1] = c.ambient[1] | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *capsV3) Empty(which CapType) bool { | ||||
| 	var data [2]uint32 | ||||
| 	c.getData(which, data[:]) | ||||
| 	return data[0] == 0 && data[1] == 0 | ||||
| } | ||||
|  | ||||
| func (c *capsV3) Full(which CapType) bool { | ||||
| 	var data [2]uint32 | ||||
| 	c.getData(which, data[:]) | ||||
| 	if (data[0] & 0xffffffff) != 0xffffffff { | ||||
| 		return false | ||||
| 	} | ||||
| 	return (data[1] & capUpperMask) == capUpperMask | ||||
| } | ||||
|  | ||||
| func (c *capsV3) Set(which CapType, caps ...Cap) { | ||||
| 	for _, what := range caps { | ||||
| 		var i uint | ||||
| 		if what > 31 { | ||||
| 			i = uint(what) >> 5 | ||||
| 			what %= 32 | ||||
| 		} | ||||
|  | ||||
| 		if which&EFFECTIVE != 0 { | ||||
| 			c.data[i].effective |= 1 << uint(what) | ||||
| 		} | ||||
| 		if which&PERMITTED != 0 { | ||||
| 			c.data[i].permitted |= 1 << uint(what) | ||||
| 		} | ||||
| 		if which&INHERITABLE != 0 { | ||||
| 			c.data[i].inheritable |= 1 << uint(what) | ||||
| 		} | ||||
| 		if which&BOUNDING != 0 { | ||||
| 			c.bounds[i] |= 1 << uint(what) | ||||
| 		} | ||||
| 		if which&AMBIENT != 0 { | ||||
| 			c.ambient[i] |= 1 << uint(what) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *capsV3) Unset(which CapType, caps ...Cap) { | ||||
| 	for _, what := range caps { | ||||
| 		var i uint | ||||
| 		if what > 31 { | ||||
| 			i = uint(what) >> 5 | ||||
| 			what %= 32 | ||||
| 		} | ||||
|  | ||||
| 		if which&EFFECTIVE != 0 { | ||||
| 			c.data[i].effective &= ^(1 << uint(what)) | ||||
| 		} | ||||
| 		if which&PERMITTED != 0 { | ||||
| 			c.data[i].permitted &= ^(1 << uint(what)) | ||||
| 		} | ||||
| 		if which&INHERITABLE != 0 { | ||||
| 			c.data[i].inheritable &= ^(1 << uint(what)) | ||||
| 		} | ||||
| 		if which&BOUNDING != 0 { | ||||
| 			c.bounds[i] &= ^(1 << uint(what)) | ||||
| 		} | ||||
| 		if which&AMBIENT != 0 { | ||||
| 			c.ambient[i] &= ^(1 << uint(what)) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *capsV3) Fill(kind CapType) { | ||||
| 	if kind&CAPS == CAPS { | ||||
| 		c.data[0].effective = 0xffffffff | ||||
| 		c.data[0].permitted = 0xffffffff | ||||
| 		c.data[0].inheritable = 0 | ||||
| 		c.data[1].effective = 0xffffffff | ||||
| 		c.data[1].permitted = 0xffffffff | ||||
| 		c.data[1].inheritable = 0 | ||||
| 	} | ||||
|  | ||||
| 	if kind&BOUNDS == BOUNDS { | ||||
| 		c.bounds[0] = 0xffffffff | ||||
| 		c.bounds[1] = 0xffffffff | ||||
| 	} | ||||
| 	if kind&AMBS == AMBS { | ||||
| 		c.ambient[0] = 0xffffffff | ||||
| 		c.ambient[1] = 0xffffffff | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *capsV3) Clear(kind CapType) { | ||||
| 	if kind&CAPS == CAPS { | ||||
| 		c.data[0].effective = 0 | ||||
| 		c.data[0].permitted = 0 | ||||
| 		c.data[0].inheritable = 0 | ||||
| 		c.data[1].effective = 0 | ||||
| 		c.data[1].permitted = 0 | ||||
| 		c.data[1].inheritable = 0 | ||||
| 	} | ||||
|  | ||||
| 	if kind&BOUNDS == BOUNDS { | ||||
| 		c.bounds[0] = 0 | ||||
| 		c.bounds[1] = 0 | ||||
| 	} | ||||
| 	if kind&AMBS == AMBS { | ||||
| 		c.ambient[0] = 0 | ||||
| 		c.ambient[1] = 0 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *capsV3) StringCap(which CapType) (ret string) { | ||||
| 	return mkStringCap(c, which) | ||||
| } | ||||
|  | ||||
| func (c *capsV3) String() (ret string) { | ||||
| 	return mkString(c, BOUNDING) | ||||
| } | ||||
|  | ||||
| func (c *capsV3) Load() (err error) { | ||||
| 	err = capget(&c.hdr, &c.data[0]) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	var status_path string | ||||
|  | ||||
| 	if c.hdr.pid == 0 { | ||||
| 		status_path = fmt.Sprintf("/proc/self/status") | ||||
| 	} else { | ||||
| 		status_path = fmt.Sprintf("/proc/%d/status", c.hdr.pid) | ||||
| 	} | ||||
|  | ||||
| 	f, err := os.Open(status_path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	b := bufio.NewReader(f) | ||||
| 	for { | ||||
| 		line, e := b.ReadString('\n') | ||||
| 		if e != nil { | ||||
| 			if e != io.EOF { | ||||
| 				err = e | ||||
| 			} | ||||
| 			break | ||||
| 		} | ||||
| 		if strings.HasPrefix(line, "CapB") { | ||||
| 			fmt.Sscanf(line[4:], "nd:  %08x%08x", &c.bounds[1], &c.bounds[0]) | ||||
| 			continue | ||||
| 		} | ||||
| 		if strings.HasPrefix(line, "CapA") { | ||||
| 			fmt.Sscanf(line[4:], "mb:  %08x%08x", &c.ambient[1], &c.ambient[0]) | ||||
| 			continue | ||||
| 		} | ||||
| 	} | ||||
| 	f.Close() | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (c *capsV3) Apply(kind CapType) (err error) { | ||||
| 	if kind&BOUNDS == BOUNDS { | ||||
| 		var data [2]capData | ||||
| 		err = capget(&c.hdr, &data[0]) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		if (1<<uint(CAP_SETPCAP))&data[0].effective != 0 { | ||||
| 			for i := Cap(0); i <= CAP_LAST_CAP; i++ { | ||||
| 				if c.Get(BOUNDING, i) { | ||||
| 					continue | ||||
| 				} | ||||
| 				err = prctl(syscall.PR_CAPBSET_DROP, uintptr(i), 0, 0, 0) | ||||
| 				if err != nil { | ||||
| 					// Ignore EINVAL since the capability may not be supported in this system. | ||||
| 					if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINVAL { | ||||
| 						err = nil | ||||
| 						continue | ||||
| 					} | ||||
| 					return | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if kind&CAPS == CAPS { | ||||
| 		err = capset(&c.hdr, &c.data[0]) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if kind&AMBS == AMBS { | ||||
| 		for i := Cap(0); i <= CAP_LAST_CAP; i++ { | ||||
| 			action := pr_CAP_AMBIENT_LOWER | ||||
| 			if c.Get(AMBIENT, i) { | ||||
| 				action = pr_CAP_AMBIENT_RAISE | ||||
| 			} | ||||
| 			err := prctl(pr_CAP_AMBIENT, action, uintptr(i), 0, 0) | ||||
| 			// Ignore EINVAL as not supported on kernels before 4.3 | ||||
| 			if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINVAL { | ||||
| 				err = nil | ||||
| 				continue | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func newFile(path string) (c Capabilities, err error) { | ||||
| 	c = &capsFile{path: path} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| type capsFile struct { | ||||
| 	path string | ||||
| 	data vfscapData | ||||
| } | ||||
|  | ||||
| func (c *capsFile) Get(which CapType, what Cap) bool { | ||||
| 	var i uint | ||||
| 	if what > 31 { | ||||
| 		if c.data.version == 1 { | ||||
| 			return false | ||||
| 		} | ||||
| 		i = uint(what) >> 5 | ||||
| 		what %= 32 | ||||
| 	} | ||||
|  | ||||
| 	switch which { | ||||
| 	case EFFECTIVE: | ||||
| 		return (1<<uint(what))&c.data.effective[i] != 0 | ||||
| 	case PERMITTED: | ||||
| 		return (1<<uint(what))&c.data.data[i].permitted != 0 | ||||
| 	case INHERITABLE: | ||||
| 		return (1<<uint(what))&c.data.data[i].inheritable != 0 | ||||
| 	} | ||||
|  | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func (c *capsFile) getData(which CapType, dest []uint32) { | ||||
| 	switch which { | ||||
| 	case EFFECTIVE: | ||||
| 		dest[0] = c.data.effective[0] | ||||
| 		dest[1] = c.data.effective[1] | ||||
| 	case PERMITTED: | ||||
| 		dest[0] = c.data.data[0].permitted | ||||
| 		dest[1] = c.data.data[1].permitted | ||||
| 	case INHERITABLE: | ||||
| 		dest[0] = c.data.data[0].inheritable | ||||
| 		dest[1] = c.data.data[1].inheritable | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *capsFile) Empty(which CapType) bool { | ||||
| 	var data [2]uint32 | ||||
| 	c.getData(which, data[:]) | ||||
| 	return data[0] == 0 && data[1] == 0 | ||||
| } | ||||
|  | ||||
| func (c *capsFile) Full(which CapType) bool { | ||||
| 	var data [2]uint32 | ||||
| 	c.getData(which, data[:]) | ||||
| 	if c.data.version == 0 { | ||||
| 		return (data[0] & 0x7fffffff) == 0x7fffffff | ||||
| 	} | ||||
| 	if (data[0] & 0xffffffff) != 0xffffffff { | ||||
| 		return false | ||||
| 	} | ||||
| 	return (data[1] & capUpperMask) == capUpperMask | ||||
| } | ||||
|  | ||||
| func (c *capsFile) Set(which CapType, caps ...Cap) { | ||||
| 	for _, what := range caps { | ||||
| 		var i uint | ||||
| 		if what > 31 { | ||||
| 			if c.data.version == 1 { | ||||
| 				continue | ||||
| 			} | ||||
| 			i = uint(what) >> 5 | ||||
| 			what %= 32 | ||||
| 		} | ||||
|  | ||||
| 		if which&EFFECTIVE != 0 { | ||||
| 			c.data.effective[i] |= 1 << uint(what) | ||||
| 		} | ||||
| 		if which&PERMITTED != 0 { | ||||
| 			c.data.data[i].permitted |= 1 << uint(what) | ||||
| 		} | ||||
| 		if which&INHERITABLE != 0 { | ||||
| 			c.data.data[i].inheritable |= 1 << uint(what) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *capsFile) Unset(which CapType, caps ...Cap) { | ||||
| 	for _, what := range caps { | ||||
| 		var i uint | ||||
| 		if what > 31 { | ||||
| 			if c.data.version == 1 { | ||||
| 				continue | ||||
| 			} | ||||
| 			i = uint(what) >> 5 | ||||
| 			what %= 32 | ||||
| 		} | ||||
|  | ||||
| 		if which&EFFECTIVE != 0 { | ||||
| 			c.data.effective[i] &= ^(1 << uint(what)) | ||||
| 		} | ||||
| 		if which&PERMITTED != 0 { | ||||
| 			c.data.data[i].permitted &= ^(1 << uint(what)) | ||||
| 		} | ||||
| 		if which&INHERITABLE != 0 { | ||||
| 			c.data.data[i].inheritable &= ^(1 << uint(what)) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *capsFile) Fill(kind CapType) { | ||||
| 	if kind&CAPS == CAPS { | ||||
| 		c.data.effective[0] = 0xffffffff | ||||
| 		c.data.data[0].permitted = 0xffffffff | ||||
| 		c.data.data[0].inheritable = 0 | ||||
| 		if c.data.version == 2 { | ||||
| 			c.data.effective[1] = 0xffffffff | ||||
| 			c.data.data[1].permitted = 0xffffffff | ||||
| 			c.data.data[1].inheritable = 0 | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *capsFile) Clear(kind CapType) { | ||||
| 	if kind&CAPS == CAPS { | ||||
| 		c.data.effective[0] = 0 | ||||
| 		c.data.data[0].permitted = 0 | ||||
| 		c.data.data[0].inheritable = 0 | ||||
| 		if c.data.version == 2 { | ||||
| 			c.data.effective[1] = 0 | ||||
| 			c.data.data[1].permitted = 0 | ||||
| 			c.data.data[1].inheritable = 0 | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *capsFile) StringCap(which CapType) (ret string) { | ||||
| 	return mkStringCap(c, which) | ||||
| } | ||||
|  | ||||
| func (c *capsFile) String() (ret string) { | ||||
| 	return mkString(c, INHERITABLE) | ||||
| } | ||||
|  | ||||
| func (c *capsFile) Load() (err error) { | ||||
| 	return getVfsCap(c.path, &c.data) | ||||
| } | ||||
|  | ||||
| func (c *capsFile) Apply(kind CapType) (err error) { | ||||
| 	if kind&CAPS == CAPS { | ||||
| 		return setVfsCap(c.path, &c.data) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										19
									
								
								vendor/github.com/syndtr/gocapability/capability/capability_noop.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								vendor/github.com/syndtr/gocapability/capability/capability_noop.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,19 +0,0 @@ | ||||
| // Copyright (c) 2013, Suryandaru Triandana <syndtr@gmail.com> | ||||
| // All rights reserved. | ||||
| // | ||||
| // Use of this source code is governed by a BSD-style license that can be | ||||
| // found in the LICENSE file. | ||||
|  | ||||
| // +build !linux | ||||
|  | ||||
| package capability | ||||
|  | ||||
| import "errors" | ||||
|  | ||||
| func newPid(pid int) (Capabilities, error) { | ||||
| 	return nil, errors.New("not supported") | ||||
| } | ||||
|  | ||||
| func newFile(path string) (Capabilities, error) { | ||||
| 	return nil, errors.New("not supported") | ||||
| } | ||||
							
								
								
									
										309
									
								
								vendor/github.com/syndtr/gocapability/capability/enum.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										309
									
								
								vendor/github.com/syndtr/gocapability/capability/enum.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,309 +0,0 @@ | ||||
| // Copyright (c) 2013, Suryandaru Triandana <syndtr@gmail.com> | ||||
| // All rights reserved. | ||||
| // | ||||
| // Use of this source code is governed by a BSD-style license that can be | ||||
| // found in the LICENSE file. | ||||
|  | ||||
| package capability | ||||
|  | ||||
| type CapType uint | ||||
|  | ||||
| func (c CapType) String() string { | ||||
| 	switch c { | ||||
| 	case EFFECTIVE: | ||||
| 		return "effective" | ||||
| 	case PERMITTED: | ||||
| 		return "permitted" | ||||
| 	case INHERITABLE: | ||||
| 		return "inheritable" | ||||
| 	case BOUNDING: | ||||
| 		return "bounding" | ||||
| 	case CAPS: | ||||
| 		return "caps" | ||||
| 	case AMBIENT: | ||||
| 		return "ambient" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	EFFECTIVE CapType = 1 << iota | ||||
| 	PERMITTED | ||||
| 	INHERITABLE | ||||
| 	BOUNDING | ||||
| 	AMBIENT | ||||
|  | ||||
| 	CAPS   = EFFECTIVE | PERMITTED | INHERITABLE | ||||
| 	BOUNDS = BOUNDING | ||||
| 	AMBS   = AMBIENT | ||||
| ) | ||||
|  | ||||
| //go:generate go run enumgen/gen.go | ||||
| type Cap int | ||||
|  | ||||
| // POSIX-draft defined capabilities and Linux extensions. | ||||
| // | ||||
| // Defined in https://github.com/torvalds/linux/blob/master/include/uapi/linux/capability.h | ||||
| const ( | ||||
| 	// In a system with the [_POSIX_CHOWN_RESTRICTED] option defined, this | ||||
| 	// overrides the restriction of changing file ownership and group | ||||
| 	// ownership. | ||||
| 	CAP_CHOWN = Cap(0) | ||||
|  | ||||
| 	// Override all DAC access, including ACL execute access if | ||||
| 	// [_POSIX_ACL] is defined. Excluding DAC access covered by | ||||
| 	// CAP_LINUX_IMMUTABLE. | ||||
| 	CAP_DAC_OVERRIDE = Cap(1) | ||||
|  | ||||
| 	// Overrides all DAC restrictions regarding read and search on files | ||||
| 	// and directories, including ACL restrictions if [_POSIX_ACL] is | ||||
| 	// defined. Excluding DAC access covered by CAP_LINUX_IMMUTABLE. | ||||
| 	CAP_DAC_READ_SEARCH = Cap(2) | ||||
|  | ||||
| 	// Overrides all restrictions about allowed operations on files, where | ||||
| 	// file owner ID must be equal to the user ID, except where CAP_FSETID | ||||
| 	// is applicable. It doesn't override MAC and DAC restrictions. | ||||
| 	CAP_FOWNER = Cap(3) | ||||
|  | ||||
| 	// Overrides the following restrictions that the effective user ID | ||||
| 	// shall match the file owner ID when setting the S_ISUID and S_ISGID | ||||
| 	// bits on that file; that the effective group ID (or one of the | ||||
| 	// supplementary group IDs) shall match the file owner ID when setting | ||||
| 	// the S_ISGID bit on that file; that the S_ISUID and S_ISGID bits are | ||||
| 	// cleared on successful return from chown(2) (not implemented). | ||||
| 	CAP_FSETID = Cap(4) | ||||
|  | ||||
| 	// Overrides the restriction that the real or effective user ID of a | ||||
| 	// process sending a signal must match the real or effective user ID | ||||
| 	// of the process receiving the signal. | ||||
| 	CAP_KILL = Cap(5) | ||||
|  | ||||
| 	// Allows setgid(2) manipulation | ||||
| 	// Allows setgroups(2) | ||||
| 	// Allows forged gids on socket credentials passing. | ||||
| 	CAP_SETGID = Cap(6) | ||||
|  | ||||
| 	// Allows set*uid(2) manipulation (including fsuid). | ||||
| 	// Allows forged pids on socket credentials passing. | ||||
| 	CAP_SETUID = Cap(7) | ||||
|  | ||||
| 	// Linux-specific capabilities | ||||
|  | ||||
| 	// Without VFS support for capabilities: | ||||
| 	//   Transfer any capability in your permitted set to any pid, | ||||
| 	//   remove any capability in your permitted set from any pid | ||||
| 	// With VFS support for capabilities (neither of above, but) | ||||
| 	//   Add any capability from current's capability bounding set | ||||
| 	//     to the current process' inheritable set | ||||
| 	//   Allow taking bits out of capability bounding set | ||||
| 	//   Allow modification of the securebits for a process | ||||
| 	CAP_SETPCAP = Cap(8) | ||||
|  | ||||
| 	// Allow modification of S_IMMUTABLE and S_APPEND file attributes | ||||
| 	CAP_LINUX_IMMUTABLE = Cap(9) | ||||
|  | ||||
| 	// Allows binding to TCP/UDP sockets below 1024 | ||||
| 	// Allows binding to ATM VCIs below 32 | ||||
| 	CAP_NET_BIND_SERVICE = Cap(10) | ||||
|  | ||||
| 	// Allow broadcasting, listen to multicast | ||||
| 	CAP_NET_BROADCAST = Cap(11) | ||||
|  | ||||
| 	// Allow interface configuration | ||||
| 	// Allow administration of IP firewall, masquerading and accounting | ||||
| 	// Allow setting debug option on sockets | ||||
| 	// Allow modification of routing tables | ||||
| 	// Allow setting arbitrary process / process group ownership on | ||||
| 	// sockets | ||||
| 	// Allow binding to any address for transparent proxying (also via NET_RAW) | ||||
| 	// Allow setting TOS (type of service) | ||||
| 	// Allow setting promiscuous mode | ||||
| 	// Allow clearing driver statistics | ||||
| 	// Allow multicasting | ||||
| 	// Allow read/write of device-specific registers | ||||
| 	// Allow activation of ATM control sockets | ||||
| 	CAP_NET_ADMIN = Cap(12) | ||||
|  | ||||
| 	// Allow use of RAW sockets | ||||
| 	// Allow use of PACKET sockets | ||||
| 	// Allow binding to any address for transparent proxying (also via NET_ADMIN) | ||||
| 	CAP_NET_RAW = Cap(13) | ||||
|  | ||||
| 	// Allow locking of shared memory segments | ||||
| 	// Allow mlock and mlockall (which doesn't really have anything to do | ||||
| 	// with IPC) | ||||
| 	CAP_IPC_LOCK = Cap(14) | ||||
|  | ||||
| 	// Override IPC ownership checks | ||||
| 	CAP_IPC_OWNER = Cap(15) | ||||
|  | ||||
| 	// Insert and remove kernel modules - modify kernel without limit | ||||
| 	CAP_SYS_MODULE = Cap(16) | ||||
|  | ||||
| 	// Allow ioperm/iopl access | ||||
| 	// Allow sending USB messages to any device via /proc/bus/usb | ||||
| 	CAP_SYS_RAWIO = Cap(17) | ||||
|  | ||||
| 	// Allow use of chroot() | ||||
| 	CAP_SYS_CHROOT = Cap(18) | ||||
|  | ||||
| 	// Allow ptrace() of any process | ||||
| 	CAP_SYS_PTRACE = Cap(19) | ||||
|  | ||||
| 	// Allow configuration of process accounting | ||||
| 	CAP_SYS_PACCT = Cap(20) | ||||
|  | ||||
| 	// Allow configuration of the secure attention key | ||||
| 	// Allow administration of the random device | ||||
| 	// Allow examination and configuration of disk quotas | ||||
| 	// Allow setting the domainname | ||||
| 	// Allow setting the hostname | ||||
| 	// Allow calling bdflush() | ||||
| 	// Allow mount() and umount(), setting up new smb connection | ||||
| 	// Allow some autofs root ioctls | ||||
| 	// Allow nfsservctl | ||||
| 	// Allow VM86_REQUEST_IRQ | ||||
| 	// Allow to read/write pci config on alpha | ||||
| 	// Allow irix_prctl on mips (setstacksize) | ||||
| 	// Allow flushing all cache on m68k (sys_cacheflush) | ||||
| 	// Allow removing semaphores | ||||
| 	// Used instead of CAP_CHOWN to "chown" IPC message queues, semaphores | ||||
| 	// and shared memory | ||||
| 	// Allow locking/unlocking of shared memory segment | ||||
| 	// Allow turning swap on/off | ||||
| 	// Allow forged pids on socket credentials passing | ||||
| 	// Allow setting readahead and flushing buffers on block devices | ||||
| 	// Allow setting geometry in floppy driver | ||||
| 	// Allow turning DMA on/off in xd driver | ||||
| 	// Allow administration of md devices (mostly the above, but some | ||||
| 	// extra ioctls) | ||||
| 	// Allow tuning the ide driver | ||||
| 	// Allow access to the nvram device | ||||
| 	// Allow administration of apm_bios, serial and bttv (TV) device | ||||
| 	// Allow manufacturer commands in isdn CAPI support driver | ||||
| 	// Allow reading non-standardized portions of pci configuration space | ||||
| 	// Allow DDI debug ioctl on sbpcd driver | ||||
| 	// Allow setting up serial ports | ||||
| 	// Allow sending raw qic-117 commands | ||||
| 	// Allow enabling/disabling tagged queuing on SCSI controllers and sending | ||||
| 	// arbitrary SCSI commands | ||||
| 	// Allow setting encryption key on loopback filesystem | ||||
| 	// Allow setting zone reclaim policy | ||||
| 	// Allow everything under CAP_BPF and CAP_PERFMON for backward compatibility | ||||
| 	CAP_SYS_ADMIN = Cap(21) | ||||
|  | ||||
| 	// Allow use of reboot() | ||||
| 	CAP_SYS_BOOT = Cap(22) | ||||
|  | ||||
| 	// Allow raising priority and setting priority on other (different | ||||
| 	// UID) processes | ||||
| 	// Allow use of FIFO and round-robin (realtime) scheduling on own | ||||
| 	// processes and setting the scheduling algorithm used by another | ||||
| 	// process. | ||||
| 	// Allow setting cpu affinity on other processes | ||||
| 	CAP_SYS_NICE = Cap(23) | ||||
|  | ||||
| 	// Override resource limits. Set resource limits. | ||||
| 	// Override quota limits. | ||||
| 	// Override reserved space on ext2 filesystem | ||||
| 	// Modify data journaling mode on ext3 filesystem (uses journaling | ||||
| 	// resources) | ||||
| 	// NOTE: ext2 honors fsuid when checking for resource overrides, so | ||||
| 	// you can override using fsuid too | ||||
| 	// Override size restrictions on IPC message queues | ||||
| 	// Allow more than 64hz interrupts from the real-time clock | ||||
| 	// Override max number of consoles on console allocation | ||||
| 	// Override max number of keymaps | ||||
| 	// Control memory reclaim behavior | ||||
| 	CAP_SYS_RESOURCE = Cap(24) | ||||
|  | ||||
| 	// Allow manipulation of system clock | ||||
| 	// Allow irix_stime on mips | ||||
| 	// Allow setting the real-time clock | ||||
| 	CAP_SYS_TIME = Cap(25) | ||||
|  | ||||
| 	// Allow configuration of tty devices | ||||
| 	// Allow vhangup() of tty | ||||
| 	CAP_SYS_TTY_CONFIG = Cap(26) | ||||
|  | ||||
| 	// Allow the privileged aspects of mknod() | ||||
| 	CAP_MKNOD = Cap(27) | ||||
|  | ||||
| 	// Allow taking of leases on files | ||||
| 	CAP_LEASE = Cap(28) | ||||
|  | ||||
| 	CAP_AUDIT_WRITE   = Cap(29) | ||||
| 	CAP_AUDIT_CONTROL = Cap(30) | ||||
| 	CAP_SETFCAP       = Cap(31) | ||||
|  | ||||
| 	// Override MAC access. | ||||
| 	// The base kernel enforces no MAC policy. | ||||
| 	// An LSM may enforce a MAC policy, and if it does and it chooses | ||||
| 	// to implement capability based overrides of that policy, this is | ||||
| 	// the capability it should use to do so. | ||||
| 	CAP_MAC_OVERRIDE = Cap(32) | ||||
|  | ||||
| 	// Allow MAC configuration or state changes. | ||||
| 	// The base kernel requires no MAC configuration. | ||||
| 	// An LSM may enforce a MAC policy, and if it does and it chooses | ||||
| 	// to implement capability based checks on modifications to that | ||||
| 	// policy or the data required to maintain it, this is the | ||||
| 	// capability it should use to do so. | ||||
| 	CAP_MAC_ADMIN = Cap(33) | ||||
|  | ||||
| 	// Allow configuring the kernel's syslog (printk behaviour) | ||||
| 	CAP_SYSLOG = Cap(34) | ||||
|  | ||||
| 	// Allow triggering something that will wake the system | ||||
| 	CAP_WAKE_ALARM = Cap(35) | ||||
|  | ||||
| 	// Allow preventing system suspends | ||||
| 	CAP_BLOCK_SUSPEND = Cap(36) | ||||
|  | ||||
| 	// Allow reading the audit log via multicast netlink socket | ||||
| 	CAP_AUDIT_READ = Cap(37) | ||||
|  | ||||
| 	// Allow system performance and observability privileged operations | ||||
| 	// using perf_events, i915_perf and other kernel subsystems | ||||
| 	CAP_PERFMON = Cap(38) | ||||
|  | ||||
| 	// CAP_BPF allows the following BPF operations: | ||||
| 	// - Creating all types of BPF maps | ||||
| 	// - Advanced verifier features | ||||
| 	//   - Indirect variable access | ||||
| 	//   - Bounded loops | ||||
| 	//   - BPF to BPF function calls | ||||
| 	//   - Scalar precision tracking | ||||
| 	//   - Larger complexity limits | ||||
| 	//   - Dead code elimination | ||||
| 	//   - And potentially other features | ||||
| 	// - Loading BPF Type Format (BTF) data | ||||
| 	// - Retrieve xlated and JITed code of BPF programs | ||||
| 	// - Use bpf_spin_lock() helper | ||||
| 	// | ||||
| 	// CAP_PERFMON relaxes the verifier checks further: | ||||
| 	// - BPF progs can use of pointer-to-integer conversions | ||||
| 	// - speculation attack hardening measures are bypassed | ||||
| 	// - bpf_probe_read to read arbitrary kernel memory is allowed | ||||
| 	// - bpf_trace_printk to print kernel memory is allowed | ||||
| 	// | ||||
| 	// CAP_SYS_ADMIN is required to use bpf_probe_write_user. | ||||
| 	// | ||||
| 	// CAP_SYS_ADMIN is required to iterate system wide loaded | ||||
| 	// programs, maps, links, BTFs and convert their IDs to file descriptors. | ||||
| 	// | ||||
| 	// CAP_PERFMON and CAP_BPF are required to load tracing programs. | ||||
| 	// CAP_NET_ADMIN and CAP_BPF are required to load networking programs. | ||||
| 	CAP_BPF = Cap(39) | ||||
|  | ||||
| 	// Allow checkpoint/restore related operations. | ||||
| 	// Introduced in kernel 5.9 | ||||
| 	CAP_CHECKPOINT_RESTORE = Cap(40) | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// Highest valid capability of the running kernel. | ||||
| 	CAP_LAST_CAP = Cap(63) | ||||
|  | ||||
| 	capUpperMask = ^uint32(0) | ||||
| ) | ||||
							
								
								
									
										138
									
								
								vendor/github.com/syndtr/gocapability/capability/enum_gen.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										138
									
								
								vendor/github.com/syndtr/gocapability/capability/enum_gen.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,138 +0,0 @@ | ||||
| // generated file; DO NOT EDIT - use go generate in directory with source | ||||
|  | ||||
| package capability | ||||
|  | ||||
| func (c Cap) String() string { | ||||
| 	switch c { | ||||
| 	case CAP_CHOWN: | ||||
| 		return "chown" | ||||
| 	case CAP_DAC_OVERRIDE: | ||||
| 		return "dac_override" | ||||
| 	case CAP_DAC_READ_SEARCH: | ||||
| 		return "dac_read_search" | ||||
| 	case CAP_FOWNER: | ||||
| 		return "fowner" | ||||
| 	case CAP_FSETID: | ||||
| 		return "fsetid" | ||||
| 	case CAP_KILL: | ||||
| 		return "kill" | ||||
| 	case CAP_SETGID: | ||||
| 		return "setgid" | ||||
| 	case CAP_SETUID: | ||||
| 		return "setuid" | ||||
| 	case CAP_SETPCAP: | ||||
| 		return "setpcap" | ||||
| 	case CAP_LINUX_IMMUTABLE: | ||||
| 		return "linux_immutable" | ||||
| 	case CAP_NET_BIND_SERVICE: | ||||
| 		return "net_bind_service" | ||||
| 	case CAP_NET_BROADCAST: | ||||
| 		return "net_broadcast" | ||||
| 	case CAP_NET_ADMIN: | ||||
| 		return "net_admin" | ||||
| 	case CAP_NET_RAW: | ||||
| 		return "net_raw" | ||||
| 	case CAP_IPC_LOCK: | ||||
| 		return "ipc_lock" | ||||
| 	case CAP_IPC_OWNER: | ||||
| 		return "ipc_owner" | ||||
| 	case CAP_SYS_MODULE: | ||||
| 		return "sys_module" | ||||
| 	case CAP_SYS_RAWIO: | ||||
| 		return "sys_rawio" | ||||
| 	case CAP_SYS_CHROOT: | ||||
| 		return "sys_chroot" | ||||
| 	case CAP_SYS_PTRACE: | ||||
| 		return "sys_ptrace" | ||||
| 	case CAP_SYS_PACCT: | ||||
| 		return "sys_pacct" | ||||
| 	case CAP_SYS_ADMIN: | ||||
| 		return "sys_admin" | ||||
| 	case CAP_SYS_BOOT: | ||||
| 		return "sys_boot" | ||||
| 	case CAP_SYS_NICE: | ||||
| 		return "sys_nice" | ||||
| 	case CAP_SYS_RESOURCE: | ||||
| 		return "sys_resource" | ||||
| 	case CAP_SYS_TIME: | ||||
| 		return "sys_time" | ||||
| 	case CAP_SYS_TTY_CONFIG: | ||||
| 		return "sys_tty_config" | ||||
| 	case CAP_MKNOD: | ||||
| 		return "mknod" | ||||
| 	case CAP_LEASE: | ||||
| 		return "lease" | ||||
| 	case CAP_AUDIT_WRITE: | ||||
| 		return "audit_write" | ||||
| 	case CAP_AUDIT_CONTROL: | ||||
| 		return "audit_control" | ||||
| 	case CAP_SETFCAP: | ||||
| 		return "setfcap" | ||||
| 	case CAP_MAC_OVERRIDE: | ||||
| 		return "mac_override" | ||||
| 	case CAP_MAC_ADMIN: | ||||
| 		return "mac_admin" | ||||
| 	case CAP_SYSLOG: | ||||
| 		return "syslog" | ||||
| 	case CAP_WAKE_ALARM: | ||||
| 		return "wake_alarm" | ||||
| 	case CAP_BLOCK_SUSPEND: | ||||
| 		return "block_suspend" | ||||
| 	case CAP_AUDIT_READ: | ||||
| 		return "audit_read" | ||||
| 	case CAP_PERFMON: | ||||
| 		return "perfmon" | ||||
| 	case CAP_BPF: | ||||
| 		return "bpf" | ||||
| 	case CAP_CHECKPOINT_RESTORE: | ||||
| 		return "checkpoint_restore" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| // List returns list of all supported capabilities | ||||
| func List() []Cap { | ||||
| 	return []Cap{ | ||||
| 		CAP_CHOWN, | ||||
| 		CAP_DAC_OVERRIDE, | ||||
| 		CAP_DAC_READ_SEARCH, | ||||
| 		CAP_FOWNER, | ||||
| 		CAP_FSETID, | ||||
| 		CAP_KILL, | ||||
| 		CAP_SETGID, | ||||
| 		CAP_SETUID, | ||||
| 		CAP_SETPCAP, | ||||
| 		CAP_LINUX_IMMUTABLE, | ||||
| 		CAP_NET_BIND_SERVICE, | ||||
| 		CAP_NET_BROADCAST, | ||||
| 		CAP_NET_ADMIN, | ||||
| 		CAP_NET_RAW, | ||||
| 		CAP_IPC_LOCK, | ||||
| 		CAP_IPC_OWNER, | ||||
| 		CAP_SYS_MODULE, | ||||
| 		CAP_SYS_RAWIO, | ||||
| 		CAP_SYS_CHROOT, | ||||
| 		CAP_SYS_PTRACE, | ||||
| 		CAP_SYS_PACCT, | ||||
| 		CAP_SYS_ADMIN, | ||||
| 		CAP_SYS_BOOT, | ||||
| 		CAP_SYS_NICE, | ||||
| 		CAP_SYS_RESOURCE, | ||||
| 		CAP_SYS_TIME, | ||||
| 		CAP_SYS_TTY_CONFIG, | ||||
| 		CAP_MKNOD, | ||||
| 		CAP_LEASE, | ||||
| 		CAP_AUDIT_WRITE, | ||||
| 		CAP_AUDIT_CONTROL, | ||||
| 		CAP_SETFCAP, | ||||
| 		CAP_MAC_OVERRIDE, | ||||
| 		CAP_MAC_ADMIN, | ||||
| 		CAP_SYSLOG, | ||||
| 		CAP_WAKE_ALARM, | ||||
| 		CAP_BLOCK_SUSPEND, | ||||
| 		CAP_AUDIT_READ, | ||||
| 		CAP_PERFMON, | ||||
| 		CAP_BPF, | ||||
| 		CAP_CHECKPOINT_RESTORE, | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										154
									
								
								vendor/github.com/syndtr/gocapability/capability/syscall_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										154
									
								
								vendor/github.com/syndtr/gocapability/capability/syscall_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,154 +0,0 @@ | ||||
| // Copyright (c) 2013, Suryandaru Triandana <syndtr@gmail.com> | ||||
| // All rights reserved. | ||||
| // | ||||
| // Use of this source code is governed by a BSD-style license that can be | ||||
| // found in the LICENSE file. | ||||
|  | ||||
| package capability | ||||
|  | ||||
| import ( | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| type capHeader struct { | ||||
| 	version uint32 | ||||
| 	pid     int32 | ||||
| } | ||||
|  | ||||
| type capData struct { | ||||
| 	effective   uint32 | ||||
| 	permitted   uint32 | ||||
| 	inheritable uint32 | ||||
| } | ||||
|  | ||||
| func capget(hdr *capHeader, data *capData) (err error) { | ||||
| 	_, _, e1 := syscall.Syscall(syscall.SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0) | ||||
| 	if e1 != 0 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func capset(hdr *capHeader, data *capData) (err error) { | ||||
| 	_, _, e1 := syscall.Syscall(syscall.SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0) | ||||
| 	if e1 != 0 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // not yet in syscall | ||||
| const ( | ||||
| 	pr_CAP_AMBIENT           = 47 | ||||
| 	pr_CAP_AMBIENT_IS_SET    = uintptr(1) | ||||
| 	pr_CAP_AMBIENT_RAISE     = uintptr(2) | ||||
| 	pr_CAP_AMBIENT_LOWER     = uintptr(3) | ||||
| 	pr_CAP_AMBIENT_CLEAR_ALL = uintptr(4) | ||||
| ) | ||||
|  | ||||
| func prctl(option int, arg2, arg3, arg4, arg5 uintptr) (err error) { | ||||
| 	_, _, e1 := syscall.Syscall6(syscall.SYS_PRCTL, uintptr(option), arg2, arg3, arg4, arg5, 0) | ||||
| 	if e1 != 0 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	vfsXattrName = "security.capability" | ||||
|  | ||||
| 	vfsCapVerMask = 0xff000000 | ||||
| 	vfsCapVer1    = 0x01000000 | ||||
| 	vfsCapVer2    = 0x02000000 | ||||
|  | ||||
| 	vfsCapFlagMask      = ^vfsCapVerMask | ||||
| 	vfsCapFlageffective = 0x000001 | ||||
|  | ||||
| 	vfscapDataSizeV1 = 4 * (1 + 2*1) | ||||
| 	vfscapDataSizeV2 = 4 * (1 + 2*2) | ||||
| ) | ||||
|  | ||||
| type vfscapData struct { | ||||
| 	magic uint32 | ||||
| 	data  [2]struct { | ||||
| 		permitted   uint32 | ||||
| 		inheritable uint32 | ||||
| 	} | ||||
| 	effective [2]uint32 | ||||
| 	version   int8 | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	_vfsXattrName *byte | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	_vfsXattrName, _ = syscall.BytePtrFromString(vfsXattrName) | ||||
| } | ||||
|  | ||||
| func getVfsCap(path string, dest *vfscapData) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = syscall.BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_vfsXattrName)), uintptr(unsafe.Pointer(dest)), vfscapDataSizeV2, 0, 0) | ||||
| 	if e1 != 0 { | ||||
| 		if e1 == syscall.ENODATA { | ||||
| 			dest.version = 2 | ||||
| 			return | ||||
| 		} | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	switch dest.magic & vfsCapVerMask { | ||||
| 	case vfsCapVer1: | ||||
| 		dest.version = 1 | ||||
| 		if r0 != vfscapDataSizeV1 { | ||||
| 			return syscall.EINVAL | ||||
| 		} | ||||
| 		dest.data[1].permitted = 0 | ||||
| 		dest.data[1].inheritable = 0 | ||||
| 	case vfsCapVer2: | ||||
| 		dest.version = 2 | ||||
| 		if r0 != vfscapDataSizeV2 { | ||||
| 			return syscall.EINVAL | ||||
| 		} | ||||
| 	default: | ||||
| 		return syscall.EINVAL | ||||
| 	} | ||||
| 	if dest.magic&vfsCapFlageffective != 0 { | ||||
| 		dest.effective[0] = dest.data[0].permitted | dest.data[0].inheritable | ||||
| 		dest.effective[1] = dest.data[1].permitted | dest.data[1].inheritable | ||||
| 	} else { | ||||
| 		dest.effective[0] = 0 | ||||
| 		dest.effective[1] = 0 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func setVfsCap(path string, data *vfscapData) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = syscall.BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var size uintptr | ||||
| 	if data.version == 1 { | ||||
| 		data.magic = vfsCapVer1 | ||||
| 		size = vfscapDataSizeV1 | ||||
| 	} else if data.version == 2 { | ||||
| 		data.magic = vfsCapVer2 | ||||
| 		if data.effective[0] != 0 || data.effective[1] != 0 { | ||||
| 			data.magic |= vfsCapFlageffective | ||||
| 		} | ||||
| 		size = vfscapDataSizeV2 | ||||
| 	} else { | ||||
| 		return syscall.EINVAL | ||||
| 	} | ||||
| 	_, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_vfsXattrName)), uintptr(unsafe.Pointer(data)), size, 0, 0) | ||||
| 	if e1 != 0 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										41
									
								
								vendor/golang.org/x/net/bpf/asm.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										41
									
								
								vendor/golang.org/x/net/bpf/asm.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,41 +0,0 @@ | ||||
| // Copyright 2016 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package bpf | ||||
|  | ||||
| import "fmt" | ||||
|  | ||||
| // Assemble converts insts into raw instructions suitable for loading | ||||
| // into a BPF virtual machine. | ||||
| // | ||||
| // Currently, no optimization is attempted, the assembled program flow | ||||
| // is exactly as provided. | ||||
| func Assemble(insts []Instruction) ([]RawInstruction, error) { | ||||
| 	ret := make([]RawInstruction, len(insts)) | ||||
| 	var err error | ||||
| 	for i, inst := range insts { | ||||
| 		ret[i], err = inst.Assemble() | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("assembling instruction %d: %s", i+1, err) | ||||
| 		} | ||||
| 	} | ||||
| 	return ret, nil | ||||
| } | ||||
|  | ||||
| // Disassemble attempts to parse raw back into | ||||
| // Instructions. Unrecognized RawInstructions are assumed to be an | ||||
| // extension not implemented by this package, and are passed through | ||||
| // unchanged to the output. The allDecoded value reports whether insts | ||||
| // contains no RawInstructions. | ||||
| func Disassemble(raw []RawInstruction) (insts []Instruction, allDecoded bool) { | ||||
| 	insts = make([]Instruction, len(raw)) | ||||
| 	allDecoded = true | ||||
| 	for i, r := range raw { | ||||
| 		insts[i] = r.Disassemble() | ||||
| 		if _, ok := insts[i].(RawInstruction); ok { | ||||
| 			allDecoded = false | ||||
| 		} | ||||
| 	} | ||||
| 	return insts, allDecoded | ||||
| } | ||||
							
								
								
									
										222
									
								
								vendor/golang.org/x/net/bpf/constants.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										222
									
								
								vendor/golang.org/x/net/bpf/constants.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,222 +0,0 @@ | ||||
| // Copyright 2016 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package bpf | ||||
|  | ||||
| // A Register is a register of the BPF virtual machine. | ||||
| type Register uint16 | ||||
|  | ||||
| const ( | ||||
| 	// RegA is the accumulator register. RegA is always the | ||||
| 	// destination register of ALU operations. | ||||
| 	RegA Register = iota | ||||
| 	// RegX is the indirection register, used by LoadIndirect | ||||
| 	// operations. | ||||
| 	RegX | ||||
| ) | ||||
|  | ||||
| // An ALUOp is an arithmetic or logic operation. | ||||
| type ALUOp uint16 | ||||
|  | ||||
| // ALU binary operation types. | ||||
| const ( | ||||
| 	ALUOpAdd ALUOp = iota << 4 | ||||
| 	ALUOpSub | ||||
| 	ALUOpMul | ||||
| 	ALUOpDiv | ||||
| 	ALUOpOr | ||||
| 	ALUOpAnd | ||||
| 	ALUOpShiftLeft | ||||
| 	ALUOpShiftRight | ||||
| 	aluOpNeg // Not exported because it's the only unary ALU operation, and gets its own instruction type. | ||||
| 	ALUOpMod | ||||
| 	ALUOpXor | ||||
| ) | ||||
|  | ||||
| // A JumpTest is a comparison operator used in conditional jumps. | ||||
| type JumpTest uint16 | ||||
|  | ||||
| // Supported operators for conditional jumps. | ||||
| // K can be RegX for JumpIfX | ||||
| const ( | ||||
| 	// K == A | ||||
| 	JumpEqual JumpTest = iota | ||||
| 	// K != A | ||||
| 	JumpNotEqual | ||||
| 	// K > A | ||||
| 	JumpGreaterThan | ||||
| 	// K < A | ||||
| 	JumpLessThan | ||||
| 	// K >= A | ||||
| 	JumpGreaterOrEqual | ||||
| 	// K <= A | ||||
| 	JumpLessOrEqual | ||||
| 	// K & A != 0 | ||||
| 	JumpBitsSet | ||||
| 	// K & A == 0 | ||||
| 	JumpBitsNotSet | ||||
| ) | ||||
|  | ||||
| // An Extension is a function call provided by the kernel that | ||||
| // performs advanced operations that are expensive or impossible | ||||
| // within the BPF virtual machine. | ||||
| // | ||||
| // Extensions are only implemented by the Linux kernel. | ||||
| // | ||||
| // TODO: should we prune this list? Some of these extensions seem | ||||
| // either broken or near-impossible to use correctly, whereas other | ||||
| // (len, random, ifindex) are quite useful. | ||||
| type Extension int | ||||
|  | ||||
| // Extension functions available in the Linux kernel. | ||||
| const ( | ||||
| 	// extOffset is the negative maximum number of instructions used | ||||
| 	// to load instructions by overloading the K argument. | ||||
| 	extOffset = -0x1000 | ||||
| 	// ExtLen returns the length of the packet. | ||||
| 	ExtLen Extension = 1 | ||||
| 	// ExtProto returns the packet's L3 protocol type. | ||||
| 	ExtProto Extension = 0 | ||||
| 	// ExtType returns the packet's type (skb->pkt_type in the kernel) | ||||
| 	// | ||||
| 	// TODO: better documentation. How nice an API do we want to | ||||
| 	// provide for these esoteric extensions? | ||||
| 	ExtType Extension = 4 | ||||
| 	// ExtPayloadOffset returns the offset of the packet payload, or | ||||
| 	// the first protocol header that the kernel does not know how to | ||||
| 	// parse. | ||||
| 	ExtPayloadOffset Extension = 52 | ||||
| 	// ExtInterfaceIndex returns the index of the interface on which | ||||
| 	// the packet was received. | ||||
| 	ExtInterfaceIndex Extension = 8 | ||||
| 	// ExtNetlinkAttr returns the netlink attribute of type X at | ||||
| 	// offset A. | ||||
| 	ExtNetlinkAttr Extension = 12 | ||||
| 	// ExtNetlinkAttrNested returns the nested netlink attribute of | ||||
| 	// type X at offset A. | ||||
| 	ExtNetlinkAttrNested Extension = 16 | ||||
| 	// ExtMark returns the packet's mark value. | ||||
| 	ExtMark Extension = 20 | ||||
| 	// ExtQueue returns the packet's assigned hardware queue. | ||||
| 	ExtQueue Extension = 24 | ||||
| 	// ExtLinkLayerType returns the packet's hardware address type | ||||
| 	// (e.g. Ethernet, Infiniband). | ||||
| 	ExtLinkLayerType Extension = 28 | ||||
| 	// ExtRXHash returns the packets receive hash. | ||||
| 	// | ||||
| 	// TODO: figure out what this rxhash actually is. | ||||
| 	ExtRXHash Extension = 32 | ||||
| 	// ExtCPUID returns the ID of the CPU processing the current | ||||
| 	// packet. | ||||
| 	ExtCPUID Extension = 36 | ||||
| 	// ExtVLANTag returns the packet's VLAN tag. | ||||
| 	ExtVLANTag Extension = 44 | ||||
| 	// ExtVLANTagPresent returns non-zero if the packet has a VLAN | ||||
| 	// tag. | ||||
| 	// | ||||
| 	// TODO: I think this might be a lie: it reads bit 0x1000 of the | ||||
| 	// VLAN header, which changed meaning in recent revisions of the | ||||
| 	// spec - this extension may now return meaningless information. | ||||
| 	ExtVLANTagPresent Extension = 48 | ||||
| 	// ExtVLANProto returns 0x8100 if the frame has a VLAN header, | ||||
| 	// 0x88a8 if the frame has a "Q-in-Q" double VLAN header, or some | ||||
| 	// other value if no VLAN information is present. | ||||
| 	ExtVLANProto Extension = 60 | ||||
| 	// ExtRand returns a uniformly random uint32. | ||||
| 	ExtRand Extension = 56 | ||||
| ) | ||||
|  | ||||
| // The following gives names to various bit patterns used in opcode construction. | ||||
|  | ||||
| const ( | ||||
| 	opMaskCls uint16 = 0x7 | ||||
| 	// opClsLoad masks | ||||
| 	opMaskLoadDest  = 0x01 | ||||
| 	opMaskLoadWidth = 0x18 | ||||
| 	opMaskLoadMode  = 0xe0 | ||||
| 	// opClsALU & opClsJump | ||||
| 	opMaskOperand  = 0x08 | ||||
| 	opMaskOperator = 0xf0 | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	// +---------------+-----------------+---+---+---+ | ||||
| 	// | AddrMode (3b) | LoadWidth (2b)  | 0 | 0 | 0 | | ||||
| 	// +---------------+-----------------+---+---+---+ | ||||
| 	opClsLoadA uint16 = iota | ||||
| 	// +---------------+-----------------+---+---+---+ | ||||
| 	// | AddrMode (3b) | LoadWidth (2b)  | 0 | 0 | 1 | | ||||
| 	// +---------------+-----------------+---+---+---+ | ||||
| 	opClsLoadX | ||||
| 	// +---+---+---+---+---+---+---+---+ | ||||
| 	// | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | | ||||
| 	// +---+---+---+---+---+---+---+---+ | ||||
| 	opClsStoreA | ||||
| 	// +---+---+---+---+---+---+---+---+ | ||||
| 	// | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | | ||||
| 	// +---+---+---+---+---+---+---+---+ | ||||
| 	opClsStoreX | ||||
| 	// +---------------+-----------------+---+---+---+ | ||||
| 	// | Operator (4b) | OperandSrc (1b) | 1 | 0 | 0 | | ||||
| 	// +---------------+-----------------+---+---+---+ | ||||
| 	opClsALU | ||||
| 	// +-----------------------------+---+---+---+---+ | ||||
| 	// |      TestOperator (4b)      | 0 | 1 | 0 | 1 | | ||||
| 	// +-----------------------------+---+---+---+---+ | ||||
| 	opClsJump | ||||
| 	// +---+-------------------------+---+---+---+---+ | ||||
| 	// | 0 | 0 | 0 |   RetSrc (1b)   | 0 | 1 | 1 | 0 | | ||||
| 	// +---+-------------------------+---+---+---+---+ | ||||
| 	opClsReturn | ||||
| 	// +---+-------------------------+---+---+---+---+ | ||||
| 	// | 0 | 0 | 0 |  TXAorTAX (1b)  | 0 | 1 | 1 | 1 | | ||||
| 	// +---+-------------------------+---+---+---+---+ | ||||
| 	opClsMisc | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	opAddrModeImmediate uint16 = iota << 5 | ||||
| 	opAddrModeAbsolute | ||||
| 	opAddrModeIndirect | ||||
| 	opAddrModeScratch | ||||
| 	opAddrModePacketLen // actually an extension, not an addressing mode. | ||||
| 	opAddrModeMemShift | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	opLoadWidth4 uint16 = iota << 3 | ||||
| 	opLoadWidth2 | ||||
| 	opLoadWidth1 | ||||
| ) | ||||
|  | ||||
| // Operand for ALU and Jump instructions | ||||
| type opOperand uint16 | ||||
|  | ||||
| // Supported operand sources. | ||||
| const ( | ||||
| 	opOperandConstant opOperand = iota << 3 | ||||
| 	opOperandX | ||||
| ) | ||||
|  | ||||
| // An jumpOp is a conditional jump condition. | ||||
| type jumpOp uint16 | ||||
|  | ||||
| // Supported jump conditions. | ||||
| const ( | ||||
| 	opJumpAlways jumpOp = iota << 4 | ||||
| 	opJumpEqual | ||||
| 	opJumpGT | ||||
| 	opJumpGE | ||||
| 	opJumpSet | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	opRetSrcConstant uint16 = iota << 4 | ||||
| 	opRetSrcA | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	opMiscTAX = 0x00 | ||||
| 	opMiscTXA = 0x80 | ||||
| ) | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	 Kubernetes Prow Robot
					Kubernetes Prow Robot