From 10b7e95424fbb1b9155967bf8c1b1d753eee27ad Mon Sep 17 00:00:00 2001 From: Antonio Ojea Date: Fri, 16 Jul 2021 12:45:59 +0200 Subject: [PATCH] detect required capabilities --- go.mod | 1 + go.sum | 4 + nk.go | 20 +- .../linux/libs/security/libcap/cap/License | 396 +++++++++++ .../pub/linux/libs/security/libcap/cap/README | 10 + .../pub/linux/libs/security/libcap/cap/cap.go | 482 +++++++++++++ .../libs/security/libcap/cap/convenience.go | 330 +++++++++ .../linux/libs/security/libcap/cap/file.go | 412 +++++++++++ .../linux/libs/security/libcap/cap/flags.go | 179 +++++ .../pub/linux/libs/security/libcap/cap/go.mod | 5 + .../pub/linux/libs/security/libcap/cap/iab.go | 287 ++++++++ .../linux/libs/security/libcap/cap/launch.go | 356 ++++++++++ .../linux/libs/security/libcap/cap/legacy.go | 7 + .../linux/libs/security/libcap/cap/modern.go | 8 + .../linux/libs/security/libcap/cap/names.go | 431 ++++++++++++ .../libs/security/libcap/cap/oslockluster.go | 33 + .../linux/libs/security/libcap/cap/oslocks.go | 51 ++ .../libs/security/libcap/cap/syscalls.go | 121 ++++ .../linux/libs/security/libcap/cap/text.go | 325 +++++++++ .../linux/libs/security/libcap/psx/License | 396 +++++++++++ .../pub/linux/libs/security/libcap/psx/README | 28 + .../pub/linux/libs/security/libcap/psx/doc.go | 60 ++ .../pub/linux/libs/security/libcap/psx/go.mod | 3 + .../pub/linux/libs/security/libcap/psx/psx.c | 644 ++++++++++++++++++ .../pub/linux/libs/security/libcap/psx/psx.go | 19 + .../linux/libs/security/libcap/psx/psx_cgo.go | 79 +++ .../libs/security/libcap/psx/psx_syscall.h | 74 ++ vendor/modules.txt | 5 + 28 files changed, 4753 insertions(+), 13 deletions(-) create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/cap/License create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/cap/README create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/cap/cap.go create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/cap/convenience.go create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/cap/file.go create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/cap/flags.go create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/cap/go.mod create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/cap/iab.go create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/cap/launch.go create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/cap/legacy.go create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/cap/modern.go create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/cap/names.go create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/cap/oslockluster.go create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/cap/oslocks.go create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/cap/syscalls.go create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/cap/text.go create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/psx/License create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/psx/README create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/psx/doc.go create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/psx/go.mod create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/psx/psx.c create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/psx/psx.go create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/psx/psx_cgo.go create mode 100644 vendor/kernel.org/pub/linux/libs/security/libcap/psx/psx_syscall.h diff --git a/go.mod b/go.mod index 1e17ecd..165a5bc 100644 --- a/go.mod +++ b/go.mod @@ -9,4 +9,5 @@ require ( golang.org/x/net v0.0.0-20201224014010-6772e930b67b golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c gvisor.dev/gvisor v0.0.0-20210506004418-fbfeba3024f0 + kernel.org/pub/linux/libs/security/libcap/cap v1.2.51 ) diff --git a/go.sum b/go.sum index 1fdc1f0..3d08d7c 100644 --- a/go.sum +++ b/go.sum @@ -602,6 +602,10 @@ k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/kube-openapi v0.0.0-20200410163147-594e756bea31/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.51 h1:2CHkVUXuBnW/jLVgbpfJ0PRdewDCS9h45Mmp6sLhurk= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.51/go.mod h1:1H1c41mQKQi1964hjtZ/Sb+KWgRsLos79wIwOOfwTVU= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.51 h1:VXVXjnTUsA9zeHIolNb6moSXZavDe1pD8Q0lPXZEOwc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.51/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/nk.go b/nk.go index eb16456..d459dba 100644 --- a/nk.go +++ b/nk.go @@ -6,11 +6,11 @@ import ( "fmt" "log" "os" - "os/exec" "os/signal" - "strconv" "golang.org/x/sys/unix" + + "kernel.org/pub/linux/libs/security/libcap/cap" ) //go:generate bpf2go filter bpf/filter.c -- -I/usr/include -I./bpf -nostdinc -O3 @@ -65,19 +65,13 @@ func main() { k, m, 5, 2) } - cmd := exec.Command("id", "-u") - output, err := cmd.Output() - if err != nil { - log.Fatal(err) + c := cap.GetProc() + if on, _ := c.GetFlag(cap.Permitted, cap.NET_RAW); !on { + log.Fatalf("insufficient privilege to open RAW sockets - want %q, have %q", cap.NET_RAW, c) } - // 0 = root, 501 = non-root user - i, err := strconv.Atoi(string(output[:len(output)-1])) - if err != nil { - log.Fatal(err) - } - if i != 0 { - log.Fatal("This program must be run as root! (sudo)") + if on, _ := c.GetFlag(cap.Permitted, cap.SYS_RESOURCE); !on { + log.Fatalf("insufficient privilege to set rlimit - want %q, have %q", cap.SYS_RESOURCE, c) } // Parse command line flags and arguments diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/cap/License b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/License new file mode 100644 index 0000000..a0ec04e --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/License @@ -0,0 +1,396 @@ +Unless otherwise *explicitly* stated, the following text describes the +licensed conditions under which the contents of this libcap/cap release +may be used and distributed. + +The licensed conditions are one or the other of these two Licenses: + + - BSD 3-clause + - GPL v2.0 + +------------------------------------------------------------------------- +BSD 3-clause: +------------- + +Redistribution and use in source and binary forms of libcap/cap, with +or without modification, are permitted provided that the following +conditions are met: + +1. Redistributions of source code must retain any existing copyright + notice, and this entire permission notice in its entirety, + including the disclaimer of warranties. + +2. Redistributions in binary form must reproduce all prior and current + copyright notices, this list of conditions, and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +3. The name of any author may not be used to endorse or promote + products derived from this software without their specific prior + written permission. + +THIS SOFTWARE IS PROVIDED ``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 AUTHOR(S) 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. + +------------------------------------------------------------------------- +GPL v2.0: +--------- + +ALTERNATIVELY, this product may be distributed under the terms of the +GNU General Public License (v2.0 - see below), in which case the +provisions of the GNU GPL are required INSTEAD OF the above +restrictions. (This clause is necessary due to a potential conflict +between the GNU GPL and the restrictions contained in a BSD-style +copyright.) + +------------------------- +Full text of gpl-2.0.txt: +------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/cap/README b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/README new file mode 100644 index 0000000..f257d44 --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/README @@ -0,0 +1,10 @@ +Package cap is the libcap API for Linux Capabilities written in +Go. The official release announcement site for libcap is: + + https://sites.google.com/site/fullycapable/ + +Like libcap, the cap package is distributed with a "you choose" +License. Specifically: BSD three clause, or GPL2. See the License +file. + +Andrew G. Morgan diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/cap/cap.go b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/cap.go new file mode 100644 index 0000000..8273d00 --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/cap.go @@ -0,0 +1,482 @@ +// Package cap provides all the Linux Capabilities userspace library API +// bindings in native Go. +// +// Capabilities are a feature of the Linux kernel that allow fine +// grain permissions to perform privileged operations. Privileged +// operations are required to do irregular system level operations +// from code. You can read more about how Capabilities are intended to +// work here: +// +// https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/33528.pdf +// +// This package supports native Go bindings for all the features +// described in that paper as well as supporting subsequent changes to +// the kernel for other styles of inheritable Capability. +// +// Some simple things you can do with this package are: +// +// // Read and display the capabilities of the running process +// c := cap.GetProc() +// log.Printf("this process has these caps:", c) +// +// // Drop any privilege a process might have (including for root, +// // but note root 'owns' a lot of system files so a cap-limited +// // root can still do considerable damage to a running system). +// old := cap.GetProc() +// empty := cap.NewSet() +// if err := empty.SetProc(); err != nil { +// log.Fatalf("failed to drop privilege: %q -> %q: %v", old, empty, err) +// } +// now := cap.GetProc() +// if cf, _ := now.Compare(empty); cf != 0 { +// log.Fatalf("failed to fully drop privilege: have=%q, wanted=%q", now, empty) +// } +// +// The "cap" package operates with POSIX semantics for security +// state. That is all OS threads are kept in sync at all times. The +// package "kernel.org/pub/linux/libs/security/libcap/psx" is used to +// implement POSIX semantics system calls that manipulate thread state +// uniformly over the whole Go (and any CGo linked) process runtime. +// +// Note, if the Go runtime syscall interface contains the Linux +// variant syscall.AllThreadsSyscall() API (it debuted in go1.16 see +// https://github.com/golang/go/issues/1435 for its history) then the +// "libcap/psx" package will use that to invoke Capability setting +// system calls in pure Go binaries. With such an enhanced Go runtime, +// to force this behavior, use the CGO_ENABLED=0 environment variable. +// +// POSIX semantics are more secure than trying to manage privilege at +// a thread level when those threads share a common memory image as +// they do under Linux: it is trivial to exploit a vulnerability in +// one thread of a process to cause execution on any another +// thread. So, any imbalance in security state, in such cases will +// readily create an opportunity for a privilege escalation +// vulnerability. +// +// POSIX semantics also work well with Go, which deliberately tries to +// insulate the user from worrying about the number of OS threads that +// are actually running in their program. Indeed, Go can efficiently +// launch and manage tens of thousands of concurrent goroutines +// without bogging the program or wider system down. It does this by +// aggressively migrating idle threads to make progress on unblocked +// goroutines. So, inconsistent security state across OS threads can +// also lead to program misbehavior. +// +// The only exception to this process-wide common security state is +// the cap.Launcher related functionality. This briefly locks an OS +// thread to a goroutine in order to launch another executable - the +// robust implementation of this kind of support is quite subtle, so +// please read its documentation carefully, if you find that you need +// it. +// +// See https://sites.google.com/site/fullycapable/ for recent updates, +// some more complete walk-through examples of ways of using +// 'cap.Set's etc and information on how to file bugs. +// +// Copyright (c) 2019-21 Andrew G. Morgan +// +// The cap and psx packages are licensed with a (you choose) BSD +// 3-clause or GPL2. See LICENSE file for details. +package cap // import "kernel.org/pub/linux/libs/security/libcap/cap" + +import ( + "errors" + "sort" + "sync" + "syscall" + "unsafe" +) + +// Value is the type of a single capability (or permission) bit. +type Value uint + +// Flag is the type of one of the three Value dimensions held in a +// Set. It is also used in the (*IAB).Fill() method for changing the +// Bounding and Ambient Vectors. +type Flag uint + +// Effective, Permitted, Inheritable are the three Flags of Values +// held in a Set. +const ( + Effective Flag = iota + Permitted + Inheritable +) + +// String identifies a Flag value by its conventional "e", "p" or "i" +// string abbreviation. +func (f Flag) String() string { + switch f { + case Effective: + return "e" + case Permitted: + return "p" + case Inheritable: + return "i" + default: + return "" + } +} + +// data holds a 32-bit slice of the compressed bitmaps of capability +// sets as understood by the kernel. +type data [Inheritable + 1]uint32 + +// Set is an opaque capabilities container for a set of system +// capbilities. It holds individually addressable capability Value's +// for the three capability Flag's. See GetFlag() and SetFlag() for +// how to adjust them individually, and Clear() and ClearFlag() for +// how to do bulk operations. +// +// For admin tasks associated with managing namespace specific file +// capabilities, Set can also support a namespace-root-UID value which +// defaults to zero. See GetNSOwner() and SetNSOwner(). +type Set struct { + // mu protects all other members of a Set. + mu sync.RWMutex + + // flat holds Flag Value bitmaps for all capabilities + // associated with this Set. + flat []data + + // Linux specific + nsRoot int +} + +// Various known kernel magic values. +const ( + kv1 = 0x19980330 // First iteration of process capabilities (32 bits). + kv2 = 0x20071026 // First iteration of process and file capabilities (64 bits) - deprecated. + kv3 = 0x20080522 // Most recently supported process and file capabilities (64 bits). +) + +var ( + // starUp protects setting of the following values: magic, + // words, maxValues. + startUp sync.Once + + // magic holds the preferred magic number for the kernel ABI. + magic uint32 + + // words holds the number of uint32's associated with each + // capability Flag for this session. + words int + + // maxValues holds the number of bit values that are named by + // the running kernel. This is generally expected to match + // ValueCount which is autogenerated at packaging time. + maxValues uint +) + +type header struct { + magic uint32 + pid int32 +} + +// syscaller is a type for abstracting syscalls. The r* variants are +// for reading state, and can be parallelized, the w* variants need to +// be serialized so all OS threads can share state. +type syscaller struct { + r3 func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) + w3 func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) + r6 func(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) + w6 func(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) +} + +// caprcall provides a pointer etc wrapper for the system calls +// associated with getcap. +//go:uintptrescapes +func (sc *syscaller) caprcall(call uintptr, h *header, d []data) error { + x := uintptr(0) + if d != nil { + x = uintptr(unsafe.Pointer(&d[0])) + } + _, _, err := sc.r3(call, uintptr(unsafe.Pointer(h)), x, 0) + if err != 0 { + return err + } + return nil +} + +// capwcall provides a pointer etc wrapper for the system calls +// associated with setcap. +//go:uintptrescapes +func (sc *syscaller) capwcall(call uintptr, h *header, d []data) error { + x := uintptr(0) + if d != nil { + x = uintptr(unsafe.Pointer(&d[0])) + } + _, _, err := sc.w3(call, uintptr(unsafe.Pointer(h)), x, 0) + if err != 0 { + return err + } + return nil +} + +// prctlrcall provides a wrapper for the prctl systemcalls that only +// read kernel state. There is a limited number of arguments needed +// and the caller should use 0 for those not needed. +func (sc *syscaller) prctlrcall(prVal, v1, v2 uintptr) (int, error) { + r, _, err := sc.r3(syscall.SYS_PRCTL, prVal, v1, v2) + if err != 0 { + return int(r), err + } + return int(r), nil +} + +// prctlrcall6 provides a wrapper for the prctl systemcalls that only +// read kernel state and require 6 arguments - ambient cap API, I'm +// looking at you. There is a limited number of arguments needed and +// the caller should use 0 for those not needed. +func (sc *syscaller) prctlrcall6(prVal, v1, v2, v3, v4, v5 uintptr) (int, error) { + r, _, err := sc.r6(syscall.SYS_PRCTL, prVal, v1, v2, v3, v4, v5) + if err != 0 { + return int(r), err + } + return int(r), nil +} + +// prctlwcall provides a wrapper for the prctl systemcalls that +// write/modify kernel state. Where available, these will use the +// POSIX semantics fixup system calls. There is a limited number of +// arguments needed and the caller should use 0 for those not needed. +func (sc *syscaller) prctlwcall(prVal, v1, v2 uintptr) (int, error) { + r, _, err := sc.w3(syscall.SYS_PRCTL, prVal, v1, v2) + if err != 0 { + return int(r), err + } + return int(r), nil +} + +// prctlwcall6 provides a wrapper for the prctl systemcalls that +// write/modify kernel state and require 6 arguments - ambient cap +// API, I'm looking at you. (Where available, these will use the POSIX +// semantics fixup system calls). There is a limited number of +// arguments needed and the caller should use 0 for those not needed. +func (sc *syscaller) prctlwcall6(prVal, v1, v2, v3, v4, v5 uintptr) (int, error) { + r, _, err := sc.w6(syscall.SYS_PRCTL, prVal, v1, v2, v3, v4, v5) + if err != 0 { + return int(r), err + } + return int(r), nil +} + +// cInit perfoms the lazy identification of the capability vintage of +// the running system. +func (sc *syscaller) cInit() { + h := &header{ + magic: kv3, + } + sc.caprcall(syscall.SYS_CAPGET, h, nil) + magic = h.magic + switch magic { + case kv1: + words = 1 + case kv2, kv3: + words = 2 + default: + // Fall back to a known good version. + magic = kv3 + words = 2 + } + // Use the bounding set to evaluate which capabilities exist. + maxValues = uint(sort.Search(32*words, func(n int) bool { + _, err := GetBound(Value(n)) + return err != nil + })) + if maxValues == 0 { + // Fall back to using the largest value defined at build time. + maxValues = NamedCount + } +} + +// MaxBits returns the number of kernel-named capabilities discovered +// at runtime in the current system. +func MaxBits() Value { + startUp.Do(multisc.cInit) + return Value(maxValues) +} + +// NewSet returns an empty capability set. +func NewSet() *Set { + startUp.Do(multisc.cInit) + return &Set{ + flat: make([]data, words), + } +} + +// ErrBadSet indicates a nil pointer was used for a *Set, or the +// request of the Set is invalid in some way. +var ErrBadSet = errors.New("bad capability set") + +// Dup returns a copy of the specified capability set. +func (c *Set) Dup() (*Set, error) { + if c == nil || len(c.flat) == 0 { + return nil, ErrBadSet + } + n := NewSet() + c.mu.RLock() + defer c.mu.RUnlock() + copy(n.flat, c.flat) + n.nsRoot = c.nsRoot + return n, nil +} + +// GetPID returns the capability set associated with the target process +// id; pid=0 is an alias for current. +func GetPID(pid int) (*Set, error) { + v := NewSet() + if err := multisc.caprcall(syscall.SYS_CAPGET, &header{magic: magic, pid: int32(pid)}, v.flat); err != nil { + return nil, err + } + return v, nil +} + +// GetProc returns the capability Set of the current process. If the +// kernel is unable to determine the Set associated with the current +// process, the function panic()s. +func GetProc() *Set { + c, err := GetPID(0) + if err != nil { + panic(err) + } + return c +} + +func (sc *syscaller) setProc(c *Set) error { + if c == nil || len(c.flat) == 0 { + return ErrBadSet + } + return sc.capwcall(syscall.SYS_CAPSET, &header{magic: magic}, c.flat) +} + +// SetProc attempts to set the capability Set of the current +// process. The kernel will perform permission checks and an error +// will be returned if the attempt fails. Should the attempt fail +// no process capabilities will have been modified. +// +// Note, the general behavior of this call is to set the +// process-shared capabilities. However, when called from a callback +// function as part of a (*Launcher).Launch(), the call only sets the +// capabilities of the thread being used to perform the launch. +func (c *Set) SetProc() error { + state, sc := scwStateSC() + defer scwSetState(launchBlocked, state, -1) + return sc.setProc(c) +} + +// defines from uapi/linux/prctl.h +const ( + prCapBSetRead = 23 + prCapBSetDrop = 24 +) + +// GetBound determines if a specific capability is currently part of +// the local bounding set. On systems where the bounding set Value is +// not present, this function returns an error. +func GetBound(val Value) (bool, error) { + v, err := multisc.prctlrcall(prCapBSetRead, uintptr(val), 0) + if err != nil { + return false, err + } + return v > 0, nil +} + +//go:uintptrescapes +func (sc *syscaller) dropBound(val ...Value) error { + for _, v := range val { + if _, err := sc.prctlwcall(prCapBSetDrop, uintptr(v), 0); err != nil { + return err + } + } + return nil +} + +// DropBound attempts to suppress bounding set Values. The kernel will +// never allow a bounding set Value bit to be raised once successfully +// dropped. However, dropping requires the current process is +// sufficiently capable (usually via cap.SETPCAP being raised in the +// Effective flag of the process' Set). Note, the drops are performed +// in order and if one bounding value cannot be dropped, the function +// returns immediately with an error which may leave the system in an +// ill-defined state. The caller can determine where things went wrong +// using GetBound(). +func DropBound(val ...Value) error { + state, sc := scwStateSC() + defer scwSetState(launchBlocked, state, -1) + return sc.dropBound(val...) +} + +// defines from uapi/linux/prctl.h +const ( + prCapAmbient = 47 + + prCapAmbientIsSet = 1 + prCapAmbientRaise = 2 + prCapAmbientLower = 3 + prCapAmbientClearAll = 4 +) + +// GetAmbient determines if a specific capability is currently part of +// the local ambient set. On systems where the ambient set Value is +// not present, this function returns an error. +func GetAmbient(val Value) (bool, error) { + r, err := multisc.prctlrcall6(prCapAmbient, prCapAmbientIsSet, uintptr(val), 0, 0, 0) + return r > 0, err +} + +//go:uintptrescapes +func (sc *syscaller) setAmbient(enable bool, val ...Value) error { + dir := uintptr(prCapAmbientLower) + if enable { + dir = prCapAmbientRaise + } + for _, v := range val { + _, err := sc.prctlwcall6(prCapAmbient, dir, uintptr(v), 0, 0, 0) + if err != nil { + return err + } + } + return nil +} + +// SetAmbient attempts to set a specific Value bit to the state, +// enable. This function will return an error if insufficient +// permission is available to perform this task. The settings are +// performed in order and the function returns immediately an error is +// detected. Use GetAmbient() to unravel where things went +// wrong. Note, the cap package manages an abstraction IAB that +// captures all three inheritable vectors in a single type. Consider +// using that. +func SetAmbient(enable bool, val ...Value) error { + state, sc := scwStateSC() + defer scwSetState(launchBlocked, state, -1) + return sc.setAmbient(enable, val...) +} + +func (sc *syscaller) resetAmbient() error { + var v bool + var err error + + for c := Value(0); !v; c++ { + if v, err = GetAmbient(c); err != nil { + // no non-zero values found. + return nil + } + } + _, err = sc.prctlwcall6(prCapAmbient, prCapAmbientClearAll, 0, 0, 0, 0) + return err +} + +// ResetAmbient attempts to ensure the Ambient set is fully +// cleared. It works by first reading the set and if it finds any bits +// raised it will attempt a reset. The test before attempting a reset +// behavior is a workaround for situations where the Ambient API is +// locked, but a reset is not actually needed. No Ambient bit not +// already raised in both the Permitted and Inheritable Set is allowed +// to be raised by the kernel. +func ResetAmbient() error { + state, sc := scwStateSC() + defer scwSetState(launchBlocked, state, -1) + return sc.resetAmbient() +} diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/cap/convenience.go b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/convenience.go new file mode 100644 index 0000000..d604ad1 --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/convenience.go @@ -0,0 +1,330 @@ +package cap + +import ( + "errors" + "fmt" + "syscall" + "unsafe" +) + +// This file contains convenience functions for libcap, to help +// users do the right thing with respect to capabilities for +// common actions. + +// Secbits capture the prctl settable secure-bits of a process. +type Secbits uint + +// SecbitNoRoot etc are the bitmasks associated with the supported +// Secbit masks. Source: uapi/linux/securebits.h +const ( + SecbitNoRoot Secbits = 1 << iota + SecbitNoRootLocked + SecbitNoSetUIDFixup + SecbitNoSetUIDFixupLocked + SecbitKeepCaps + SecbitKeepCapsLocked + SecbitNoCapAmbientRaise + SecbitNoCapAmbientRaiseLocked +) + +const ( + securedBasicBits = SecbitNoRoot | SecbitNoRootLocked | SecbitNoSetUIDFixup | SecbitNoSetUIDFixupLocked | SecbitKeepCapsLocked + securedAmbientBits = securedBasicBits | SecbitNoCapAmbientRaise | SecbitNoCapAmbientRaiseLocked +) + +// defines from uapi/linux/prctl.h +const ( + prGetKeepCaps = 7 + prSetKeepCaps = 8 + prGetSecureBits = 27 + prSetSecureBits = 28 + prSetNoNewPrivs = 38 +) + +// GetSecbits returns the current setting of the process' Secbits. +func GetSecbits() Secbits { + v, err := multisc.prctlrcall(prGetSecureBits, 0, 0) + if err != nil { + panic(err) + } + return Secbits(v) +} + +func (sc *syscaller) setSecbits(s Secbits) error { + _, err := sc.prctlwcall(prSetSecureBits, uintptr(s), 0) + return err +} + +// Set attempts to force the process Secbits to a value. This function +// will raise cap.SETPCAP in order to achieve this operation, and will +// completely lower the Effective vector of the process returning. +func (s Secbits) Set() error { + state, sc := scwStateSC() + defer scwSetState(launchBlocked, state, -1) + return sc.setSecbits(s) +} + +// Mode summarizes a complicated secure-bits and capability mode in a +// libcap preferred way. +type Mode uint + +// ModeUncertain etc are how libcap summarizes security modes +// involving capabilities and secure-bits. +const ( + ModeUncertain Mode = iota + ModeNoPriv + ModePure1EInit + ModePure1E +) + +// GetMode assesses the current process state and summarizes it as +// a Mode. This function always succeeds. Unfamiliar modes are +// declared ModeUncertain. +func GetMode() Mode { + b := GetSecbits() + if b&securedBasicBits != securedBasicBits { + return ModeUncertain + } + + for c := Value(0); ; c++ { + v, err := GetAmbient(c) + if err != nil { + if c != 0 && b != securedAmbientBits { + return ModeUncertain + } + break + } + if v { + return ModeUncertain + } + } + + w := GetProc() + e := NewSet() + cf, _ := w.Compare(e) + + if Differs(cf, Inheritable) { + return ModePure1E + } + if Differs(cf, Permitted) || Differs(cf, Effective) { + return ModePure1EInit + } + + for c := Value(0); ; c++ { + v, err := GetBound(c) + if err != nil { + break + } + if v { + return ModePure1EInit + } + } + + return ModeNoPriv +} + +// ErrBadMode is the error returned when an attempt is made to set an +// unrecognized libcap security mode. +var ErrBadMode = errors.New("unsupported mode") + +func (sc *syscaller) setMode(m Mode) error { + w := GetProc() + defer func() { + w.ClearFlag(Effective) + sc.setProc(w) + }() + + if err := w.SetFlag(Effective, true, SETPCAP); err != nil { + return err + } + if err := sc.setProc(w); err != nil { + return err + } + + if m == ModeNoPriv || m == ModePure1EInit { + w.ClearFlag(Inheritable) + } else if m != ModePure1E { + return ErrBadMode + } + + sb := securedAmbientBits + if _, err := GetAmbient(0); err != nil { + sb = securedBasicBits + } else if err := sc.resetAmbient(); err != nil { + return err + } + + if err := sc.setSecbits(sb); err != nil { + return err + } + + if m != ModeNoPriv { + return nil + } + + for c := Value(0); sc.dropBound(c) == nil; c++ { + } + w.ClearFlag(Permitted) + + // For good measure. + sc.prctlwcall6(prSetNoNewPrivs, 1, 0, 0, 0, 0) + + return nil +} + +// Set attempts to enter the specified mode. An attempt is made to +// enter the mode, so if you prefer this operation to be a no-op if +// entering the same mode, call only if CurrentMode() disagrees with +// the desired mode. +// +// This function will raise cap.SETPCAP in order to achieve this +// operation, and will completely lower the Effective Flag of the +// process' Set before returning. This function may fail for lack of +// permission or because (some of) the Secbits are already locked for +// the current process. +func (m Mode) Set() error { + state, sc := scwStateSC() + defer scwSetState(launchBlocked, state, -1) + return sc.setMode(m) +} + +// String returns the libcap conventional string for this mode. +func (m Mode) String() string { + switch m { + case ModeUncertain: + return "UNCERTAIN" + case ModeNoPriv: + return "NOPRIV" + case ModePure1EInit: + return "PURE1E_INIT" + case ModePure1E: + return "PURE1E" + default: + return "UNKNOWN" + } +} + +func (sc *syscaller) setUID(uid int) error { + w := GetProc() + defer func() { + w.ClearFlag(Effective) + sc.setProc(w) + }() + + if err := w.SetFlag(Effective, true, SETUID); err != nil { + return err + } + + // these may or may not work depending on whether or not they + // are locked. We try them just in case. + sc.prctlwcall(prSetKeepCaps, 1, 0) + defer sc.prctlwcall(prSetKeepCaps, 0, 0) + + if err := sc.setProc(w); err != nil { + return err + } + + if _, _, err := sc.w3(syscall.SYS_SETUID, uintptr(uid), 0, 0); err != 0 { + return err + } + return nil +} + +// SetUID is a convenience function for robustly setting the UID and +// all other variants of UID (EUID etc) to the specified value without +// dropping the privilege of the current process. This function will +// raise cap.SETUID in order to achieve this operation, and will +// completely lower the Effective vector of the process before +// returning. Unlike the traditional method of dropping privilege when +// changing from [E]UID=0 to some other UID, this function only +// performs a change of UID cap.SETUID is available, and the action +// does not alter the Permitted Flag of the process' Set. +func SetUID(uid int) error { + state, sc := scwStateSC() + defer scwSetState(launchBlocked, state, -1) + return sc.setUID(uid) +} + +//go:uintptrescapes +func (sc *syscaller) setGroups(gid int, suppl []int) error { + w := GetProc() + defer func() { + w.ClearFlag(Effective) + sc.setProc(w) + }() + + if err := w.SetFlag(Effective, true, SETGID); err != nil { + return err + } + if err := sc.setProc(w); err != nil { + return err + } + + if _, _, err := sc.w3(syscall.SYS_SETGID, uintptr(gid), 0, 0); err != 0 { + return err + } + if len(suppl) == 0 { + if _, _, err := sc.w3(sysSetGroupsVariant, 0, 0, 0); err != 0 { + return err + } + return nil + } + + // On linux gid values are 32-bits. + gs := make([]uint32, len(suppl)) + for i, g := range suppl { + gs[i] = uint32(g) + } + if _, _, err := sc.w3(sysSetGroupsVariant, uintptr(len(suppl)), uintptr(unsafe.Pointer(&gs[0])), 0); err != 0 { + return err + } + return nil +} + +// SetGroups is a convenience function for robustly setting the GID +// and all other variants of GID (EGID etc) to the specified value, as +// well as setting all of the supplementary groups. This function will +// raise cap.SETGID in order to achieve this operation, and will +// completely lower the Effective Flag of the process Set before +// returning. +func SetGroups(gid int, suppl ...int) error { + state, sc := scwStateSC() + defer scwSetState(launchBlocked, state, -1) + return sc.setGroups(gid, suppl) +} + +//go:uintptrescapes + +// Prctlw is a convenience function for performing a syscall.Prctl() +// call that executes on all the threads of the process. It is called +// Prctlw because it is only appropriate to call this function when it +// is writing thread state that the caller wants to set on all OS +// threads of the process to observe POSIX semantics when Linux +// doesn't natively honor them. (Check prctl documentation for when it +// is appropriate to use this vs. a normal syscall.Prctl() call.) +func Prctlw(prVal uintptr, args ...uintptr) (int, error) { + if n := len(args); n > 5 { + return -1, fmt.Errorf("prctl supports up to 5 arguments (not %d)", n) + } + state, sc := scwStateSC() + defer scwSetState(launchBlocked, state, -1) + as := make([]uintptr, 5) + copy(as, args) + return sc.prctlwcall6(prVal, as[0], as[1], as[2], as[3], as[4]) +} + +//go:uintptrescapes + +// Prctl is a convenience function that performs a syscall.Prctl() +// that either reads state using a single OS thread, or performs a +// Prctl that is treated as a process wide setting. It is provided for +// symmetry reasons, but is equivalent to simply calling the +// corresponding syscall function. +func Prctl(prVal uintptr, args ...uintptr) (int, error) { + if n := len(args); n > 5 { + return -1, fmt.Errorf("prctl supports up to 5 arguments (not %d)", n) + } + as := make([]uintptr, 5) + copy(as, args) + return singlesc.prctlrcall6(prVal, as[0], as[1], as[2], as[3], as[4]) +} diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/cap/file.go b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/file.go new file mode 100644 index 0000000..c74e5b3 --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/file.go @@ -0,0 +1,412 @@ +package cap + +import ( + "bytes" + "encoding/binary" + "errors" + "io" + "os" + "syscall" + "unsafe" +) + +// uapi/linux/xattr.h defined. +var ( + xattrNameCaps, _ = syscall.BytePtrFromString("security.capability") +) + +// uapi/linux/capability.h defined. +const ( + vfsCapRevisionMask = uint32(0xff000000) + vfsCapFlagsMask = ^vfsCapRevisionMask + vfsCapFlagsEffective = uint32(1) + + vfsCapRevision1 = uint32(0x01000000) + vfsCapRevision2 = uint32(0x02000000) + vfsCapRevision3 = uint32(0x03000000) +) + +// Data types stored in little-endian order. + +type vfsCaps1 struct { + MagicEtc uint32 + Data [1]struct { + Permitted, Inheritable uint32 + } +} + +type vfsCaps2 struct { + MagicEtc uint32 + Data [2]struct { + Permitted, Inheritable uint32 + } +} + +type vfsCaps3 struct { + MagicEtc uint32 + Data [2]struct { + Permitted, Inheritable uint32 + } + RootID uint32 +} + +// ErrBadSize indicates the the loaded file capability has +// an invalid number of bytes in it. +var ErrBadSize = errors.New("filecap bad size") + +// ErrBadMagic indicates that the kernel preferred magic number for +// capability Set values is not supported by this package. This +// generally implies you are using an exceptionally old +// "../libcap/cap" package. An upgrade is needed, or failing that see +// https://sites.google.com/site/fullycapable/ for how to file a bug. +var ErrBadMagic = errors.New("unsupported magic") + +// ErrBadPath indicates a failed attempt to set a file capability on +// an irregular (non-executable) file. +var ErrBadPath = errors.New("file is not a regular executable") + +// ErrOutOfRange indicates an erroneous value for MinExtFlagSize. +var ErrOutOfRange = errors.New("flag length invalid for export") + +// digestFileCap unpacks a file capability and returns it in a *Set +// form. +func digestFileCap(d []byte, sz int, err error) (*Set, error) { + if err != nil { + return nil, err + } + var raw1 vfsCaps1 + var raw2 vfsCaps2 + var raw3 vfsCaps3 + if sz < binary.Size(raw1) || sz > binary.Size(raw3) { + return nil, ErrBadSize + } + b := bytes.NewReader(d[:sz]) + var magicEtc uint32 + if err = binary.Read(b, binary.LittleEndian, &magicEtc); err != nil { + return nil, err + } + + c := NewSet() + b.Seek(0, io.SeekStart) + switch magicEtc & vfsCapRevisionMask { + case vfsCapRevision1: + if err = binary.Read(b, binary.LittleEndian, &raw1); err != nil { + return nil, err + } + data := raw1.Data[0] + c.flat[0][Permitted] = data.Permitted + c.flat[0][Inheritable] = data.Inheritable + if raw1.MagicEtc&vfsCapFlagsMask == vfsCapFlagsEffective { + c.flat[0][Effective] = data.Inheritable | data.Permitted + } + case vfsCapRevision2: + if err = binary.Read(b, binary.LittleEndian, &raw2); err != nil { + return nil, err + } + for i, data := range raw2.Data { + c.flat[i][Permitted] = data.Permitted + c.flat[i][Inheritable] = data.Inheritable + if raw2.MagicEtc&vfsCapFlagsMask == vfsCapFlagsEffective { + c.flat[i][Effective] = data.Inheritable | data.Permitted + } + } + case vfsCapRevision3: + if err = binary.Read(b, binary.LittleEndian, &raw3); err != nil { + return nil, err + } + for i, data := range raw3.Data { + c.flat[i][Permitted] = data.Permitted + c.flat[i][Inheritable] = data.Inheritable + if raw3.MagicEtc&vfsCapFlagsMask == vfsCapFlagsEffective { + c.flat[i][Effective] = data.Inheritable | data.Permitted + } + } + c.nsRoot = int(raw3.RootID) + default: + return nil, ErrBadMagic + } + return c, nil +} + +//go:uintptrescapes + +// GetFd returns the file capabilities of an open (*os.File).Fd(). +func GetFd(file *os.File) (*Set, error) { + var raw3 vfsCaps3 + d := make([]byte, binary.Size(raw3)) + sz, _, oErr := multisc.r6(syscall.SYS_FGETXATTR, uintptr(file.Fd()), uintptr(unsafe.Pointer(xattrNameCaps)), uintptr(unsafe.Pointer(&d[0])), uintptr(len(d)), 0, 0) + var err error + if oErr != 0 { + err = oErr + } + return digestFileCap(d, int(sz), err) +} + +//go:uintptrescapes + +// GetFile returns the file capabilities of a named file. +func GetFile(path string) (*Set, error) { + p, err := syscall.BytePtrFromString(path) + if err != nil { + return nil, err + } + var raw3 vfsCaps3 + d := make([]byte, binary.Size(raw3)) + sz, _, oErr := multisc.r6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(p)), uintptr(unsafe.Pointer(xattrNameCaps)), uintptr(unsafe.Pointer(&d[0])), uintptr(len(d)), 0, 0) + if oErr != 0 { + err = oErr + } + return digestFileCap(d, int(sz), err) +} + +// GetNSOwner returns the namespace owner UID of the capability Set. +func (c *Set) GetNSOwner() (int, error) { + if magic < kv3 { + return 0, ErrBadMagic + } + return c.nsRoot, nil +} + +// SetNSOwner adds an explicit namespace owner UID to the capability +// Set. This is only honored when generating file capabilities, and is +// generally for use by a setup process when installing binaries that +// use file capabilities to become capable inside a namespace to be +// administered by that UID. If capability aware code within that +// namespace writes file capabilities without explicitly setting such +// a UID, the kernel will fix-up the capabilities to be specific to +// that owner. In this way, the kernel prevents filesystem +// capabilities from leaking out of that restricted namespace. +func (c *Set) SetNSOwner(uid int) { + c.mu.Lock() + defer c.mu.Unlock() + c.nsRoot = uid +} + +// packFileCap transforms a system capability into a VFS form. Because +// of the way Linux stores capabilities in the file extended +// attributes, the process is a little lossy with respect to effective +// bits. +func (c *Set) packFileCap() ([]byte, error) { + var magic uint32 + switch words { + case 1: + if c.nsRoot != 0 { + return nil, ErrBadSet // nsRoot not supported for single DWORD caps. + } + magic = vfsCapRevision1 + case 2: + if c.nsRoot == 0 { + magic = vfsCapRevision2 + break + } + magic = vfsCapRevision3 + } + if magic == 0 { + return nil, ErrBadSize + } + eff := uint32(0) + for _, f := range c.flat { + eff |= (f[Permitted] | f[Inheritable]) & f[Effective] + } + if eff != 0 { + magic |= vfsCapFlagsEffective + } + b := new(bytes.Buffer) + binary.Write(b, binary.LittleEndian, magic) + for _, f := range c.flat { + binary.Write(b, binary.LittleEndian, f[Permitted]) + binary.Write(b, binary.LittleEndian, f[Inheritable]) + } + if c.nsRoot != 0 { + binary.Write(b, binary.LittleEndian, c.nsRoot) + } + return b.Bytes(), nil +} + +//go:uintptrescapes + +// SetFd attempts to set the file capabilities of an open +// (*os.File).Fd(). This function can also be used to delete a file's +// capabilities, by calling with c = nil. +// +// Note, Linux does not store the full Effective Value Flag in the +// metadata for the file. Only a single Effective bit is stored in +// this metadata. This single bit is non-zero if the Effective vector +// has any overlapping bits with the Permitted or Inheritable vector +// of c. This may appear suboptimal, but the reasoning behind it is +// sound. Namely, the purpose of the Effective bit it to support +// capabability unaware binaries that will only work if they magically +// launch with the needed bits already raised (this bit is sometimes +// referred to simply as the 'legacy' bit). Without *full* support for +// capability manipulation, as it is provided in this "../libcap/cap" +// package, this was the only way for Go programs to make use of +// file capabilities. +// +// The preferred way a binary will actually manipulate its +// file-acquired capabilities is to carefully and deliberately use +// this package (or libcap, assisted by libpsx, for threaded C/C++ +// family code). +func (c *Set) SetFd(file *os.File) error { + if c == nil { + if _, _, err := multisc.r6(syscall.SYS_FREMOVEXATTR, uintptr(file.Fd()), uintptr(unsafe.Pointer(xattrNameCaps)), 0, 0, 0, 0); err != 0 { + return err + } + return nil + } + c.mu.Lock() + defer c.mu.Unlock() + d, err := c.packFileCap() + if err != nil { + return err + } + if _, _, err := multisc.r6(syscall.SYS_FSETXATTR, uintptr(file.Fd()), uintptr(unsafe.Pointer(xattrNameCaps)), uintptr(unsafe.Pointer(&d[0])), uintptr(len(d)), 0, 0); err != 0 { + return err + } + return nil +} + +//go:uintptrescapes + +// SetFile attempts to set the file capabilities of the specfied +// filename. This function can also be used to delete a file's +// capabilities, by calling with c = nil. +// +// Note, see the comment for SetFd() for some non-obvious behavior of +// Linux for the Effective Value vector on the modified file. +func (c *Set) SetFile(path string) error { + fi, err := os.Stat(path) + if err != nil { + return err + } + mode := fi.Mode() + if mode&os.ModeType != 0 { + return ErrBadPath + } + if mode&os.FileMode(0111) == 0 { + return ErrBadPath + } + p, err := syscall.BytePtrFromString(path) + if err != nil { + return err + } + if c == nil { + if _, _, err := multisc.r6(syscall.SYS_REMOVEXATTR, uintptr(unsafe.Pointer(p)), uintptr(unsafe.Pointer(xattrNameCaps)), 0, 0, 0, 0); err != 0 { + return err + } + return nil + } + c.mu.Lock() + defer c.mu.Unlock() + d, err := c.packFileCap() + if err != nil { + return err + } + if _, _, err := multisc.r6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(p)), uintptr(unsafe.Pointer(xattrNameCaps)), uintptr(unsafe.Pointer(&d[0])), uintptr(len(d)), 0, 0); err != 0 { + return err + } + return nil +} + +// ExtMagic is the 32-bit (little endian) magic for an external +// capability set. It can be used to transmit capabilities in binary +// format in a Linux portable way. The format is: +// . +const ExtMagic = uint32(0x5101c290) + +// Import imports a Set from a byte array where it has been stored in +// a portable (lossless) way. That is values exported by +// libcap.cap_copy_ext() and Export(). +func Import(d []byte) (*Set, error) { + b := bytes.NewBuffer(d) + var m uint32 + if err := binary.Read(b, binary.LittleEndian, &m); err != nil { + return nil, ErrBadSize + } else if m != ExtMagic { + return nil, ErrBadMagic + } + var n byte + if err := binary.Read(b, binary.LittleEndian, &n); err != nil { + return nil, ErrBadSize + } + c := NewSet() + if int(n) > 4*words { + return nil, ErrBadSize + } + f := make([]byte, 3) + for i := 0; i < words; i++ { + for j := uint(0); n > 0 && j < 4; j++ { + n-- + if x, err := b.Read(f); err != nil || x != 3 { + return nil, ErrBadSize + } + sh := 8 * j + c.flat[i][Effective] |= uint32(f[0]) << sh + c.flat[i][Permitted] |= uint32(f[1]) << sh + c.flat[i][Inheritable] |= uint32(f[2]) << sh + } + } + return c, nil +} + +// To strictly match libcap, this value defaults to 8. Setting it to +// zero can generate smaller external representations. Such smaller +// representations can be imported by libcap and the Go package just +// fine, we just default to the default libcap representation for +// legacy reasons. +var MinExtFlagSize = uint(8) + +// Export exports a Set into a lossless byte array format where it is +// stored in a portable way. Note, any namespace owner in the Set +// content is not exported by this function. +// +// Note, Export() generates exported byte streams that are importable +// by libcap.cap_copy_int() as well as Import(). +func (c *Set) Export() ([]byte, error) { + if c == nil { + return nil, ErrBadSet + } + if MinExtFlagSize > 255 { + return nil, ErrOutOfRange + } + b := new(bytes.Buffer) + binary.Write(b, binary.LittleEndian, ExtMagic) + c.mu.Lock() + defer c.mu.Unlock() + var n = uint(0) + for i, f := range c.flat { + if nn := 4 * uint(i); nn+4 > n { + if u := f[Effective] | f[Permitted] | f[Inheritable]; u != 0 { + n = nn + for ; u != 0; u >>= 8 { + n++ + } + } + } + } + if n < MinExtFlagSize { + n = MinExtFlagSize + } + b.Write([]byte{byte(n)}) + for _, f := range c.flat { + if n == 0 { + break + } + eff, per, inh := f[Effective], f[Permitted], f[Inheritable] + for i := 0; n > 0 && i < 4; i++ { + n-- + b.Write([]byte{ + byte(eff & 0xff), + byte(per & 0xff), + byte(inh & 0xff), + }) + eff >>= 8 + per >>= 8 + inh >>= 8 + } + } + for n > 0 { + n-- + b.Write([]byte{0, 0, 0}) + } + return b.Bytes(), nil +} diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/cap/flags.go b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/flags.go new file mode 100644 index 0000000..83a871a --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/flags.go @@ -0,0 +1,179 @@ +package cap + +import "errors" + +// GetFlag determines if the requested bit is enabled in the Flag +// vector of the capability Set. +func (c *Set) GetFlag(vec Flag, val Value) (bool, error) { + if c == nil || len(c.flat) == 0 { + // Checked this first, because otherwise we are sure + // cInit has been called. + return false, ErrBadSet + } + offset, mask, err := bitOf(vec, val) + if err != nil { + return false, err + } + c.mu.RLock() + defer c.mu.RUnlock() + return c.flat[offset][vec]&mask != 0, nil +} + +// SetFlag sets the requested bits to the indicated enable state. This +// function does not perform any security checks, so values can be set +// out-of-order. Only when the Set is used to SetProc() etc., will the +// bits be checked for validity and permission by the kernel. If the +// function returns an error, the Set will not be modified. +func (c *Set) SetFlag(vec Flag, enable bool, val ...Value) error { + if c == nil || len(c.flat) == 0 { + // Checked this first, because otherwise we are sure + // cInit has been called. + return ErrBadSet + } + c.mu.Lock() + defer c.mu.Unlock() + // Make a backup. + replace := make([]uint32, words) + for i := range replace { + replace[i] = c.flat[i][vec] + } + var err error + for _, v := range val { + offset, mask, err2 := bitOf(vec, v) + if err2 != nil { + err = err2 + break + } + if enable { + c.flat[offset][vec] |= mask + } else { + c.flat[offset][vec] &= ^mask + } + } + if err == nil { + return nil + } + // Clean up. + for i, bits := range replace { + c.flat[i][vec] = bits + } + return err +} + +// Clear fully clears a capability set. +func (c *Set) Clear() error { + if c == nil || len(c.flat) == 0 { + return ErrBadSet + } + // startUp.Do(cInit) is not called here because c cannot be + // initialized except via this package and doing that will + // perform that call at least once (sic). + c.mu.Lock() + defer c.mu.Unlock() + c.flat = make([]data, words) + c.nsRoot = 0 + return nil +} + +// Fill copies the from flag values into the to flag. With this +// function, you can raise all of the permitted values in the +// effective flag with c.Fill(cap.Effective, cap.Permitted). +func (c *Set) Fill(to, from Flag) error { + if c == nil || len(c.flat) == 0 { + return ErrBadSet + } + if to > Inheritable || from > Inheritable { + return ErrBadValue + } + c.mu.Lock() + defer c.mu.Unlock() + for i := range c.flat { + c.flat[i][to] = c.flat[i][from] + } + return nil +} + +// ErrBadValue indicates a bad capability value was specified. +var ErrBadValue = errors.New("bad capability value") + +// bitOf converts from a Value into the offset and mask for a +// specific Value bit in the compressed (kernel ABI) representation of +// a capability vector. If the requested bit is unsupported, an error +// is returned. +func bitOf(vec Flag, val Value) (uint, uint32, error) { + if vec > Inheritable || val > Value(words*32) { + return 0, 0, ErrBadValue + } + u := uint(val) + return u / 32, uint32(1) << (u % 32), nil +} + +// allMask returns the mask of valid bits in the all mask for index. +func allMask(index uint) (mask uint32) { + if maxValues == 0 { + panic("uninitialized package") + } + base := 32 * uint(index) + if maxValues <= base { + return + } + if maxValues >= 32+base { + mask = ^mask + return + } + mask = uint32((uint64(1) << (maxValues % 32)) - 1) + return +} + +// forceFlag sets 'all' capability values (supported by the kernel) of +// a flag vector to enable. +func (c *Set) forceFlag(vec Flag, enable bool) error { + if c == nil || len(c.flat) == 0 || vec > Inheritable { + return ErrBadSet + } + m := uint32(0) + if enable { + m = ^m + } + c.mu.Lock() + defer c.mu.Unlock() + for i := range c.flat { + c.flat[i][vec] = m & allMask(uint(i)) + } + return nil +} + +// ClearFlag clears a specific vector of Values associated with the +// specified Flag. +func (c *Set) ClearFlag(vec Flag) error { + return c.forceFlag(vec, false) +} + +// Compare returns 0 if c and d are identical in content. Otherwise, +// this function returns a non-zero value of 3 independent bits: +// (differE ? 1:0) | (differP ? 2:0) | (differI ? 4:0). The Differs() +// function can be used to test for a difference in a specific Flag. +func (c *Set) Compare(d *Set) (uint, error) { + if c == nil || len(c.flat) == 0 || d == nil || len(d.flat) == 0 { + return 0, ErrBadSet + } + var cf uint + for i := 0; i < words; i++ { + if c.flat[i][Effective]^d.flat[i][Effective] != 0 { + cf |= (1 << Effective) + } + if c.flat[i][Permitted]^d.flat[i][Permitted] != 0 { + cf |= (1 << Permitted) + } + if c.flat[i][Inheritable]^d.flat[i][Inheritable] != 0 { + cf |= (1 << Inheritable) + } + } + return cf, nil +} + +// Differs processes the result of Compare and determines if the +// Flag's components were different. +func Differs(cf uint, vec Flag) bool { + return cf&(1<> 5, uint32(1) << (u & 31) +} + +// IAB holds a summary of all of the inheritable capability vectors: +// Inh, Amb and Bound. The Bound vector is the logical inverse (two's +// complement) of the process' Bounding set. That is, raising a Value +// in the Bound (think blocked) vector is equivalent to dropping that +// Value from the process' Bounding set. This convention is used to +// support the empty IAB as being mostly harmless. +type IAB struct { + a, i, nb []uint32 +} + +// Vector enumerates which of the inheritable IAB capability vectors +// is being manipulated. +type Vector uint + +// Inh, Amb, Bound enumerate the IAB vector components. (Vector) Inh +// is equivalent to (Flag) Inheritable. They are named differently for +// syntax/type checking reasons. +const ( + Inh Vector = iota + Amb + Bound +) + +// String identifies a Vector value by its conventional I A or B +// string abbreviation. +func (v Vector) String() string { + switch v { + case Inh: + return "I" + case Amb: + return "A" + case Bound: + return "B" + default: + return "" + } +} + +// IABInit returns an empty IAB. +func IABInit() *IAB { + startUp.Do(multisc.cInit) + return &IAB{ + i: make([]uint32, words), + a: make([]uint32, words), + nb: make([]uint32, words), + } +} + +// IABGetProc summarizes the Inh, Amb and Bound capabilty vectors of +// the current process. +func IABGetProc() *IAB { + iab := IABInit() + current := GetProc() + iab.Fill(Inh, current, Inheritable) + for c := MaxBits(); c > 0; { + c-- + offset, mask := omask(c) + if a, _ := GetAmbient(c); a { + iab.a[offset] |= mask + } + if b, err := GetBound(c); err == nil && !b { + iab.nb[offset] |= mask + } + } + return iab +} + +// IABFromText parses a string representing an IAB, as generated +// by IAB.String(), to generate an IAB. +func IABFromText(text string) (*IAB, error) { + iab := IABInit() + if len(text) == 0 { + return iab, nil + } + for _, f := range strings.Split(text, ",") { + var i, a, nb bool + var j int + for j = 0; j < len(f); j++ { + switch f[j : j+1] { + case "!": + nb = true + case "^": + i = true + a = true + case "%": + i = true + default: + goto done + } + } + done: + c, err := FromName(f[j:]) + if err != nil { + return nil, err + } + offset, mask := omask(c) + if i || !nb { + iab.i[offset] |= mask + } + if a { + iab.a[offset] |= mask + } + if nb { + iab.nb[offset] |= mask + } + } + return iab, nil +} + +// String serializes an IAB to a string format. +func (iab *IAB) String() string { + var vs []string + for c := Value(0); c < Value(maxValues); c++ { + offset, mask := omask(c) + i := (iab.i[offset] & mask) != 0 + a := (iab.a[offset] & mask) != 0 + nb := (iab.nb[offset] & mask) != 0 + var cs []string + if nb { + cs = append(cs, "!") + } + if a { + cs = append(cs, "^") + } else if nb && i { + cs = append(cs, "%") + } + if nb || a || i { + vs = append(vs, strings.Join(cs, "")+c.String()) + } + } + return strings.Join(vs, ",") +} + +func (sc *syscaller) iabSetProc(iab *IAB) (err error) { + temp := GetProc() + var raising uint32 + for i := 0; i < words; i++ { + newI := iab.i[i] + oldIP := temp.flat[i][Inheritable] | temp.flat[i][Permitted] + raising |= (newI & ^oldIP) | iab.a[i] | iab.nb[i] + temp.flat[i][Inheritable] = newI + } + working, err2 := temp.Dup() + if err2 != nil { + err = err2 + return + } + if raising != 0 { + if err = working.SetFlag(Effective, true, SETPCAP); err != nil { + return + } + if err = sc.setProc(working); err != nil { + return + } + } + defer func() { + if err2 := sc.setProc(temp); err == nil { + err = err2 + } + }() + if err = sc.resetAmbient(); err != nil { + return + } + for c := Value(maxValues); c > 0; { + c-- + offset, mask := omask(c) + if iab.a[offset]&mask != 0 { + err = sc.setAmbient(true, c) + } + if err == nil && iab.nb[offset]&mask != 0 { + err = sc.dropBound(c) + } + if err != nil { + return + } + } + return +} + +// SetProc attempts to change the Inheritable, Ambient and Bounding +// capabilty vectors of the current process using the content, +// iab. The Bounding vector strongly affects the potential for setting +// other bits, so this function carefully performs the the combined +// operation in the most flexible manner. +func (iab *IAB) SetProc() error { + state, sc := scwStateSC() + defer scwSetState(launchBlocked, state, -1) + return sc.iabSetProc(iab) +} + +// GetVector returns the raised state of the specific capability bit +// of the indicated vector. +func (iab *IAB) GetVector(vec Vector, val Value) (bool, error) { + if val >= MaxBits() { + return false, ErrBadValue + } + offset, mask := omask(val) + switch vec { + case Inh: + return (iab.i[offset] & mask) != 0, nil + case Amb: + return (iab.a[offset] & mask) != 0, nil + case Bound: + return (iab.nb[offset] & mask) != 0, nil + default: + return false, ErrBadValue + } +} + +// SetVector sets all of the vals in the specified vector to the +// raised value. Note, the Ambient vector cannot contain values not raised +// in the Inh vector, so setting values directly in one vector may have +// the side effect of mirroring the value in the other vector to +// maintain this constraint. Note, raising a Bound vector bit is +// equivalent to lowering the Bounding vector of the process (when +// successfully applied with (*IAB).SetProc()). +func (iab *IAB) SetVector(vec Vector, raised bool, vals ...Value) error { + for _, val := range vals { + if val >= Value(maxValues) { + return ErrBadValue + } + offset, mask := omask(val) + switch vec { + case Inh: + if raised { + iab.i[offset] |= mask + } else { + iab.i[offset] &= ^mask + iab.a[offset] &= ^mask + } + case Amb: + if raised { + iab.a[offset] |= mask + iab.i[offset] |= mask + } else { + iab.a[offset] &= ^mask + } + case Bound: + if raised { + iab.nb[offset] |= mask + } else { + iab.nb[offset] &= ^mask + } + default: + return ErrBadValue + } + } + return nil +} + +// Fill fills one of the Inh, Amb and Bound capability vectors from +// one of the flag vectors of a Set. Note, filling the Inh vector +// will mask the Amb vector, and filling the Amb vector may raise +// entries in the Inh vector. Further, when filling the Bound vector, +// the bits are inverted from what you might expect - that is lowered +// bits from the Set will be raised in the Bound vector. +func (iab *IAB) Fill(vec Vector, c *Set, flag Flag) error { + if len(c.flat) != 0 || flag > Inheritable { + return ErrBadSet + } + for i := 0; i < words; i++ { + flat := c.flat[i][flag] + switch vec { + case Inh: + iab.i[i] = flat + iab.a[i] &= ^flat + case Amb: + iab.a[i] = flat + iab.i[i] |= ^flat + case Bound: + iab.nb[i] = ^flat + default: + return ErrBadSet + } + } + return nil +} diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/cap/launch.go b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/launch.go new file mode 100644 index 0000000..fa2576b --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/launch.go @@ -0,0 +1,356 @@ +package cap + +import ( + "errors" + "os" + "runtime" + "syscall" + "unsafe" +) + +// Launcher holds a configuration for executing an optional callback +// function and/or launching a child process with capability state +// different from the parent. +// +// Note, go1.10 is the earliest version of the Go toolchain that can +// support this abstraction. +type Launcher struct { + // Note, path and args must be set, or callbackFn. They cannot + // both be empty. In such cases .Launch() will error out. + path string + args []string + env []string + + callbackFn func(pa *syscall.ProcAttr, data interface{}) error + + // The following are only honored when path is non empty. + changeUIDs bool + uid int + + changeGIDs bool + gid int + groups []int + + changeMode bool + mode Mode + + iab *IAB + + chroot string +} + +// NewLauncher returns a new launcher for the specified program path +// and args with the specified environment. +func NewLauncher(path string, args []string, env []string) *Launcher { + return &Launcher{ + path: path, + args: args, + env: env, + } +} + +// FuncLauncher returns a new launcher whose purpose is to only +// execute fn in a disposable security context. This is a more bare +// bones variant of the more elaborate program launcher returned by +// cap.NewLauncher(). +// +// The properties of fn are similar to those supplied via +// (*Launcher).Callback(fn) method. However, this launcher is bare +// bones because, when launching, all privilege management performed +// by the fn() is fully discarded when the fn() completes exection. +func FuncLauncher(fn func(interface{}) error) *Launcher { + return &Launcher{ + callbackFn: func(ignored *syscall.ProcAttr, data interface{}) error { + return fn(data) + }, + } +} + +// Callback changes the callback function for Launch() to call before +// changing privilege. The only thing that is assumed is that the OS +// thread in use to call this callback function at launch time will be +// the one that ultimately calls fork to complete the launch of a path +// specified executable. Any returned error value of said function +// will terminate the launch process. +// +// A nil fn causes there to be no callback function invoked during a +// Launch() sequence - it will remove any pre-existing callback. +// +// If the non-nil fn requires any effective capabilities in order to +// run, they can be raised prior to calling .Launch() or inside the +// callback function itself. +// +// If the specified callback fn should call any "cap" package +// functions that change privilege state, these calls will only affect +// the launch goroutine itself. While the launch is in progress, other +// (non-launch) goroutines will block if they attempt to change +// privilege state. These routines will unblock once there are no +// in-flight launches. +// +// Note, the first argument provided to the callback function is the +// *syscall.ProcAttr value to be used when a process launch is taking +// place. A non-nil structure pointer can be modified by the callback +// to enhance the launch. For example, the .Files field can be +// overriden to affect how the launched process' stdin/out/err are +// handled. +// +// Further, the 2nd argument to the callback function is provided at +// Launch() invocation and can communicate contextual info to and from +// the callback and the main process. +func (attr *Launcher) Callback(fn func(*syscall.ProcAttr, interface{}) error) { + attr.callbackFn = fn +} + +// SetUID specifies the UID to be used by the launched command. +func (attr *Launcher) SetUID(uid int) { + attr.changeUIDs = true + attr.uid = uid +} + +// SetGroups specifies the GID and supplementary groups for the +// launched command. +func (attr *Launcher) SetGroups(gid int, groups []int) { + attr.changeGIDs = true + attr.gid = gid + attr.groups = groups +} + +// SetMode specifies the libcap Mode to be used by the launched command. +func (attr *Launcher) SetMode(mode Mode) { + attr.changeMode = true + attr.mode = mode +} + +// SetIAB specifies the AIB capability vectors to be inherited by the +// launched command. A nil value means the prevailing vectors of the +// parent will be inherited. +func (attr *Launcher) SetIAB(iab *IAB) { + attr.iab = iab +} + +// SetChroot specifies the chroot value to be used by the launched +// command. An empty value means no-change from the prevailing value. +func (attr *Launcher) SetChroot(root string) { + attr.chroot = root +} + +// lResult is used to get the result from the doomed launcher thread. +type lResult struct { + // tid holds the tid of the locked launching thread which dies + // as the launch completes. + tid int + + // pid is the pid of the launched program (path, args). In + // the case of a FuncLaunch() this value is zero on success. + // pid holds -1 in the case of error. + pid int + + // err is nil on success, but otherwise holds the reason the + // launch failed. + err error +} + +// ErrLaunchFailed is returned if a launch was aborted with no more +// specific error. +var ErrLaunchFailed = errors.New("launch failed") + +// ErrNoLaunch indicates the go runtime available to this binary does +// not reliably support launching. See cap.LaunchSupported. +var ErrNoLaunch = errors.New("launch not supported") + +// ErrAmbiguousChroot indicates that the Launcher is being used in +// addition to a callback supplied Chroot. The former should be used +// exclusively for this. +var ErrAmbiguousChroot = errors.New("use Launcher for chroot") + +// ErrAmbiguousIDs indicates that the Launcher is being used in +// addition to a callback supplied Credentials. The former should be +// used exclusively for this. +var ErrAmbiguousIDs = errors.New("use Launcher for uids and gids") + +// ErrAmbiguousAmbient indicates that the Launcher is being used in +// addition to a callback supplied ambient set and the former should +// be used exclusively in a Launch call. +var ErrAmbiguousAmbient = errors.New("use Launcher for ambient caps") + +// lName is the name we temporarily give to the launcher thread. Note, +// this will likely stick around in the process tree if the Go runtime +// is not cleaning up locked launcher OS threads. +var lName = []byte("cap-launcher\000") + +// +const prSetName = 15 + +//go:uintptrescapes +func launch(result chan<- lResult, attr *Launcher, data interface{}, quit chan<- struct{}) { + if quit != nil { + defer close(quit) + } + + pid := syscall.Getpid() + // This code waits until we are not scheduled on the parent + // thread. We will exit this thread once the child has + // launched. + runtime.LockOSThread() + tid := syscall.Gettid() + if tid == pid { + // Force the go runtime to find a new thread to run + // on. (It is really awkward to have a process' + // PID=TID thread in effectively a zomebie state. The + // Go runtime has support for it, but pstree gives + // ugly output since the prSetName value sticks around + // after launch completion... + // + // (Optimize for time to debug by reducing ugly spam + // like this.) + quit := make(chan struct{}) + go launch(result, attr, data, quit) + + // Wait for that go routine to complete. + <-quit + runtime.UnlockOSThread() + return + } + + // By never releasing the LockOSThread here, we guarantee that + // the runtime will terminate the current OS thread once this + // function returns. + scwSetState(launchIdle, launchActive, tid) + + // Name the launcher thread - transient, but helps to debug if + // the callbackFn or something else hangs up. + singlesc.prctlrcall(prSetName, uintptr(unsafe.Pointer(&lName[0])), 0) + + // Provide a way to serialize the caller on the thread + // completing. + defer close(result) + + var pa *syscall.ProcAttr + var err error + var needChroot bool + + // Only prepare a non-nil pa value if a path is provided. + if attr.path != "" { + // By default the following file descriptors are preserved for + // the child. The user should modify them in the callback for + // stdin/out/err redirection. + pa = &syscall.ProcAttr{ + Files: []uintptr{0, 1, 2}, + } + if len(attr.env) != 0 { + pa.Env = attr.env + } else { + pa.Env = os.Environ() + } + } + + if attr.callbackFn != nil { + if err = attr.callbackFn(pa, data); err != nil { + goto abort + } + if attr.path == "" { + pid = 0 + goto abort + } + } + + if needChroot, err = validatePA(pa, attr.chroot); err != nil { + goto abort + } + if attr.changeUIDs { + if err = singlesc.setUID(attr.uid); err != nil { + goto abort + } + } + if attr.changeGIDs { + if err = singlesc.setGroups(attr.gid, attr.groups); err != nil { + goto abort + } + } + if attr.changeMode { + if err = singlesc.setMode(attr.mode); err != nil { + goto abort + } + } + if attr.iab != nil { + if err = singlesc.iabSetProc(attr.iab); err != nil { + goto abort + } + } + + if needChroot { + c := GetProc() + if err = c.SetFlag(Effective, true, SYS_CHROOT); err != nil { + goto abort + } + if err = singlesc.setProc(c); err != nil { + goto abort + } + } + pid, err = syscall.ForkExec(attr.path, attr.args, pa) + +abort: + if err != nil { + pid = -1 + } + result <- lResult{ + tid: tid, + pid: pid, + err: err, + } +} + +// Launch performs a callback function and/or new program launch with +// a disposable security state. The data object, when not nil, can be +// used to communicate with the callback. It can also be used to +// return details from the callback functions execution. +// +// If the attr was created with NewLauncher(), this present function +// will return the pid of the launched process, or -1 and a non-nil +// error. +// +// If the attr was created with FuncLauncher(), this present function +// will return 0, nil if the callback function exits without +// error. Otherwise it will return -1 and the non-nil error of the +// callback return value. +// +// Note, while the disposable security state thread makes some +// oprerations seem more isolated - they are *not securely +// isolated*. Launching is inherently violating the POSIX semantics +// maintained by the rest of the "libcap/cap" package, so think of +// launching as a convenience wrapper around fork()ing. +// +// Advanced user note: if the caller of this function thinks they know +// what they are doing by using runtime.LockOSThread() before invoking +// this function, they should understand that the OS Thread invoking +// (*Launcher).Launch() is *not guaranteed* to be the one used for the +// disposable security state to perform the launch. If said caller +// needs to run something on the disposable security state thread, +// they should do it via the launch callback function mechanism. (The +// Go runtime is complicated and this is why this Launch mechanism +// provides the optional callback function.) +func (attr *Launcher) Launch(data interface{}) (int, error) { + if !LaunchSupported { + return -1, ErrNoLaunch + } + if attr.callbackFn == nil && (attr.path == "" || len(attr.args) == 0) { + return -1, ErrLaunchFailed + } + + result := make(chan lResult) + go launch(result, attr, data, nil) + for { + select { + case v, ok := <-result: + if !ok { + return -1, ErrLaunchFailed + } + if v.tid != -1 { + defer scwSetState(launchActive, launchIdle, v.tid) + } + return v.pid, v.err + default: + runtime.Gosched() + } + } +} diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/cap/legacy.go b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/legacy.go new file mode 100644 index 0000000..0bfd93e --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/legacy.go @@ -0,0 +1,7 @@ +// +build linux,arm linux,386 + +package cap + +import "syscall" + +var sysSetGroupsVariant = uintptr(syscall.SYS_SETGROUPS32) diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/cap/modern.go b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/modern.go new file mode 100644 index 0000000..ad89416 --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/modern.go @@ -0,0 +1,8 @@ +// +build linux,!arm +// +build linux,!386 + +package cap + +import "syscall" + +var sysSetGroupsVariant = uintptr(syscall.SYS_SETGROUPS) diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/cap/names.go b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/names.go new file mode 100644 index 0000000..bb69daa --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/names.go @@ -0,0 +1,431 @@ +package cap + +/* ** DO NOT EDIT THIS FILE. IT WAS AUTO-GENERATED BY LIBCAP'S GO BUILDER (mknames.go) ** */ + +// NamedCount holds the number of capability values with official +// names known at the time this libcap/cap version, was released. The +// "../libcap/cap" package is fully able to manipulate higher numbered +// capability values by numerical value. However, if you find +// cap.NamedCount < cap.MaxBits(), it is probably time to upgrade this +// package on your system. +// +// FWIW the userspace tool '/sbin/capsh' also contains a runtime check +// for the condition that libcap is behind the running kernel in this +// way. +const NamedCount = 41 + +// CHOWN etc., are the named capability values of the Linux +// kernel. The canonical source for each name is the +// "uapi/linux/capabilities.h" file. Some values may not be available +// (yet) where the kernel is older. The actual number of capabities +// supported by the running kernel can be obtained using the +// cap.MaxBits() function. +const ( + // CHOWN allows a process to arbitrarily change the user and + // group ownership of a file. + CHOWN Value = iota + + // DAC_OVERRIDE allows a process to override of all Discretionary + // Access Control (DAC) access, including ACL execute + // access. That is read, write or execute files that the + // process would otherwise not have access to. This + // excludes DAC access covered by cap.LINUX_IMMUTABLE. + DAC_OVERRIDE + + // DAC_READ_SEARCH allows a process to override all DAC restrictions + // limiting the read and search of files and + // directories. This excludes DAC access covered by + // cap.LINUX_IMMUTABLE. + DAC_READ_SEARCH + + // FOWNER allows a process to perform operations on files, even + // where file owner ID should otherwise need be equal to + // the UID, except where cap.FSETID is applicable. It + // doesn't override MAC and DAC restrictions. + FOWNER + + // FSETID allows a process to set the S_ISUID and S_ISUID bits of + // the file permissions, even when the process' effective + // UID or GID/supplementary GIDs do not match that of the + // file. + FSETID + + // KILL allows a process to send a kill(2) signal to any other + // process - overriding the limitation that there be a + // [E]UID match between source and target process. + KILL + + // SETGID allows a process to freely manipulate its own GIDs: + // - arbitrarily set the GID, EGID, REGID, RESGID values + // - arbitrarily set the supplementary GIDs + // - allows the forging of GID credentials passed over a + // socket + SETGID + + // SETUID allows a process to freely manipulate its own UIDs: + // - arbitraily set the UID, EUID, REUID and RESUID + // values + // - allows the forging of UID credentials passed over a + // socket + SETUID + + // SETPCAP allows a process to freely manipulate its inheritable + // capabilities. Linux supports the POSIX.1e Inheritable + // set, as well as Bounding and Ambient Linux extension + // vectors. This capability permits dropping bits from the + // Bounding vector. It also permits the process to raise + // Ambient vector bits that are both raised in the + // Permitted and Inheritable sets of the process. This + // capability cannot be used to raise Permitted bits, or + // Effective bits beyond those already present in the + // process' permitted set. + // + // [Historical note: prior to the advent of file + // capabilities (2008), this capability was suppressed by + // default, as its unsuppressed behavior was not + // auditable: it could asynchronously grant its own + // Permitted capabilities to and remove capabilities from + // other processes arbitraily. The former leads to + // undefined behavior, and the latter is better served by + // the kill system call.] + SETPCAP + + // LINUX_IMMUTABLE allows a process to modify the S_IMMUTABLE and + // S_APPEND file attributes. + LINUX_IMMUTABLE + + // NET_BIND_SERVICE allows a process to bind to privileged ports: + // - TCP/UDP sockets below 1024 + // - ATM VCIs below 32 + NET_BIND_SERVICE + + // NET_BROADCAST allows a process to broadcast to the network and to + // listen to multicast. + NET_BROADCAST + + // NET_ADMIN allows a process to perform network configuration + // operations: + // - interface configuration + // - administration of IP firewall, masquerading and + // accounting + // - setting debug options on sockets + // - modification of routing tables + // - setting arbitrary process, and process group + // ownership on sockets + // - binding to any address for transparent proxying + // (this is also allowed via cap.NET_RAW) + // - setting TOS (Type of service) + // - setting promiscuous mode + // - clearing driver statistics + // - multicasing + // - read/write of device-specific registers + // - activation of ATM control sockets + NET_ADMIN + + // NET_RAW allows a process to use raw networking: + // - RAW sockets + // - PACKET sockets + // - binding to any address for transparent proxying + // (also permitted via cap.NET_ADMIN) + NET_RAW + + // IPC_LOCK allows a process to lock shared memory segments for IPC + // purposes. Also enables mlock and mlockall system + // calls. + IPC_LOCK + + // IPC_OWNER allows a process to override IPC ownership checks. + IPC_OWNER + + // SYS_MODULE allows a process to initiate the loading and unloading + // of kernel modules. This capability can effectively + // modify kernel without limit. + SYS_MODULE + + // SYS_RAWIO allows a process to perform raw IO: + // - permit ioper/iopl access + // - permit sending USB messages to any device via + // /dev/bus/usb + SYS_RAWIO + + // SYS_CHROOT allows a process to perform a chroot syscall to change + // the effective root of the process' file system: + // redirect to directory "/" to some other location. + SYS_CHROOT + + // SYS_PTRACE allows a process to perform a ptrace() of any other + // process. + SYS_PTRACE + + // SYS_PACCT allows a process to configure process accounting. + SYS_PACCT + + // SYS_ADMIN allows a process to perform a somewhat arbitrary + // grab-bag of privileged operations. Over time, this + // capability should weaken as specific capabilities are + // created for subsets of cap.SYS_ADMINs functionality: + // - configuration of the secure attention key + // - administration of the random device + // - examination and configuration of disk quotas + // - setting the domainname + // - setting the hostname + // - calling bdflush() + // - mount() and umount(), setting up new SMB connection + // - some autofs root ioctls + // - nfsservctl + // - VM86_REQUEST_IRQ + // - to read/write pci config on alpha + // - irix_prctl on mips (setstacksize) + // - flushing all cache on m68k (sys_cacheflush) + // - removing semaphores + // - Used instead of cap.CHOWN to "chown" IPC message + // queues, semaphores and shared memory + // - locking/unlocking of shared memory segment + // - turning swap on/off + // - forged pids on socket credentials passing + // - setting readahead and flushing buffers on block + // devices + // - setting geometry in floppy driver + // - turning DMA on/off in xd driver + // - administration of md devices (mostly the above, but + // some extra ioctls) + // - tuning the ide driver + // - access to the nvram device + // - administration of apm_bios, serial and bttv (TV) + // device + // - manufacturer commands in isdn CAPI support driver + // - reading non-standardized portions of PCI + // configuration space + // - DDI debug ioctl on sbpcd driver + // - setting up serial ports + // - sending raw qic-117 commands + // - enabling/disabling tagged queuing on SCSI + // controllers and sending arbitrary SCSI commands + // - setting encryption key on loopback filesystem + // - setting zone reclaim policy + SYS_ADMIN + + // SYS_BOOT allows a process to initiate a reboot of the system. + SYS_BOOT + + // SYS_NICE allows a process to maipulate the execution priorities + // of arbitrary processes: + // - those involving different UIDs + // - setting their CPU affinity + // - alter the FIFO vs. round-robin (realtime) + // scheduling for itself and other processes. + SYS_NICE + + // SYS_RESOURCE allows a process to adjust resource related parameters + // of processes and the system: + // - set and override resource limits + // - override quota limits + // - override the reserved space on ext2 filesystem + // (this can also be achieved via cap.FSETID) + // - modify the data journaling mode on ext3 filesystem, + // which uses journaling resources + // - override size restrictions on IPC message queues + // - configure more than 64Hz interrupts from the + // real-time clock + // - override the maximum number of consoles for console + // allocation + // - override the maximum number of keymaps + SYS_RESOURCE + + // SYS_TIME allows a process to perform time manipulation of clocks: + // - alter the system clock + // - enable irix_stime on MIPS + // - set the real-time clock + SYS_TIME + + // SYS_TTY_CONFIG allows a process to manipulate tty devices: + // - configure tty devices + // - perform vhangup() of a tty + SYS_TTY_CONFIG + + // MKNOD allows a process to perform privileged operations with + // the mknod() system call. + MKNOD + + // LEASE allows a process to take leases on files. + LEASE + + // AUDIT_WRITE allows a process to write to the audit log via a + // unicast netlink socket. + AUDIT_WRITE + + // AUDIT_CONTROL allows a process to configure audit logging via a + // unicast netlink socket. + AUDIT_CONTROL + + // SETFCAP allows a process to set capabilities on files. + // Permits a process to uid_map the uid=0 of the + // parent user namespace into that of the child + // namespace. Also, permits a process to override + // securebits locks through user namespace + // creation. + SETFCAP + + // MAC_OVERRIDE allows a process to override Manditory Access Control + // (MAC) access. Not all kernels are configured with a MAC + // mechanism, but this is the capability reserved for + // overriding them. + MAC_OVERRIDE + + // MAC_ADMIN allows a process to configure the Mandatory Access + // Control (MAC) policy. Not all kernels are configured + // with a MAC enabled, but if they are this capability is + // reserved for code to perform administration tasks. + MAC_ADMIN + + // SYSLOG allows a process to configure the kernel's syslog + // (printk) behavior. + SYSLOG + + // WAKE_ALARM allows a process to trigger something that can wake the + // system up. + WAKE_ALARM + + // BLOCK_SUSPEND allows a process to block system suspends - prevent the + // system from entering a lower power state. + BLOCK_SUSPEND + + // AUDIT_READ allows a process to read the audit log via a multicast + // netlink socket. + AUDIT_READ + + // PERFMON allows a process to enable observability of privileged + // operations related to performance. The mechanisms + // include perf_events, i915_perf and other kernel + // subsystems. + PERFMON + + // BPF allows a process to manipulate aspects of the kernel + // enhanced Berkeley Packet Filter (BPF) system. This is + // an execution subsystem of the kernel, that manages BPF + // programs. cap.BPF permits a process to: + // - create 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 + // - potentially other features + // + // Other capabilities can be used together with cap.BFP to + // further manipulate the BPF system: + // - cap.PERFMON relaxes the verifier checks as follows: + // - BPF programs can use pointer-to-integer + // conversions + // - speculation attack hardening measures can be + // bypassed + // - bpf_probe_read to read arbitrary kernel memory is + // permitted + // - bpf_trace_printk to print the content of kernel + // memory + // - cap.SYS_ADMIN permits the following: + // - use of bpf_probe_write_user + // - iteration over the system-wide loaded programs, + // maps, links BTFs and convert their IDs to file + // descriptors. + // - cap.PERFMON is required to load tracing programs. + // - cap.NET_ADMIN is required to load networking + // programs. + BPF + + // CHECKPOINT_RESTORE allows a process to perform checkpoint + // and restore operations. Also permits + // explicit PID control via clone3() and + // also writing to ns_last_pid. + CHECKPOINT_RESTORE +) + +var names = map[Value]string{ + CHOWN: "cap_chown", + DAC_OVERRIDE: "cap_dac_override", + DAC_READ_SEARCH: "cap_dac_read_search", + FOWNER: "cap_fowner", + FSETID: "cap_fsetid", + KILL: "cap_kill", + SETGID: "cap_setgid", + SETUID: "cap_setuid", + SETPCAP: "cap_setpcap", + LINUX_IMMUTABLE: "cap_linux_immutable", + NET_BIND_SERVICE: "cap_net_bind_service", + NET_BROADCAST: "cap_net_broadcast", + NET_ADMIN: "cap_net_admin", + NET_RAW: "cap_net_raw", + IPC_LOCK: "cap_ipc_lock", + IPC_OWNER: "cap_ipc_owner", + SYS_MODULE: "cap_sys_module", + SYS_RAWIO: "cap_sys_rawio", + SYS_CHROOT: "cap_sys_chroot", + SYS_PTRACE: "cap_sys_ptrace", + SYS_PACCT: "cap_sys_pacct", + SYS_ADMIN: "cap_sys_admin", + SYS_BOOT: "cap_sys_boot", + SYS_NICE: "cap_sys_nice", + SYS_RESOURCE: "cap_sys_resource", + SYS_TIME: "cap_sys_time", + SYS_TTY_CONFIG: "cap_sys_tty_config", + MKNOD: "cap_mknod", + LEASE: "cap_lease", + AUDIT_WRITE: "cap_audit_write", + AUDIT_CONTROL: "cap_audit_control", + SETFCAP: "cap_setfcap", + MAC_OVERRIDE: "cap_mac_override", + MAC_ADMIN: "cap_mac_admin", + SYSLOG: "cap_syslog", + WAKE_ALARM: "cap_wake_alarm", + BLOCK_SUSPEND: "cap_block_suspend", + AUDIT_READ: "cap_audit_read", + PERFMON: "cap_perfmon", + BPF: "cap_bpf", + CHECKPOINT_RESTORE: "cap_checkpoint_restore", +} + +var bits = map[string]Value{ + "cap_chown": CHOWN, + "cap_dac_override": DAC_OVERRIDE, + "cap_dac_read_search": DAC_READ_SEARCH, + "cap_fowner": FOWNER, + "cap_fsetid": FSETID, + "cap_kill": KILL, + "cap_setgid": SETGID, + "cap_setuid": SETUID, + "cap_setpcap": SETPCAP, + "cap_linux_immutable": LINUX_IMMUTABLE, + "cap_net_bind_service": NET_BIND_SERVICE, + "cap_net_broadcast": NET_BROADCAST, + "cap_net_admin": NET_ADMIN, + "cap_net_raw": NET_RAW, + "cap_ipc_lock": IPC_LOCK, + "cap_ipc_owner": IPC_OWNER, + "cap_sys_module": SYS_MODULE, + "cap_sys_rawio": SYS_RAWIO, + "cap_sys_chroot": SYS_CHROOT, + "cap_sys_ptrace": SYS_PTRACE, + "cap_sys_pacct": SYS_PACCT, + "cap_sys_admin": SYS_ADMIN, + "cap_sys_boot": SYS_BOOT, + "cap_sys_nice": SYS_NICE, + "cap_sys_resource": SYS_RESOURCE, + "cap_sys_time": SYS_TIME, + "cap_sys_tty_config": SYS_TTY_CONFIG, + "cap_mknod": MKNOD, + "cap_lease": LEASE, + "cap_audit_write": AUDIT_WRITE, + "cap_audit_control": AUDIT_CONTROL, + "cap_setfcap": SETFCAP, + "cap_mac_override": MAC_OVERRIDE, + "cap_mac_admin": MAC_ADMIN, + "cap_syslog": SYSLOG, + "cap_wake_alarm": WAKE_ALARM, + "cap_block_suspend": BLOCK_SUSPEND, + "cap_audit_read": AUDIT_READ, + "cap_perfmon": PERFMON, + "cap_bpf": BPF, + "cap_checkpoint_restore": CHECKPOINT_RESTORE, +} diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/cap/oslockluster.go b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/oslockluster.go new file mode 100644 index 0000000..0b2cf2e --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/oslockluster.go @@ -0,0 +1,33 @@ +// +build !go1.10 + +package cap + +import "syscall" + +// LaunchSupported indicates that is safe to return from a locked OS +// Thread and have that OS Thread be terminated by the runtime. The +// Launch functionality really needs to rely on the fact that an +// excess of runtime.LockOSThread() vs. runtime.UnlockOSThread() calls +// in a returning go routine will cause the underlying locked OSThread +// to terminate. That feature was added to the Go runtime in version +// 1.10. +// +// See these bugs for the discussion and feature assumed by the code +// in this Launch() functionality: +// +// https://github.com/golang/go/issues/20395 +// https://github.com/golang/go/issues/20458 +// +// A value of false for this constant causes the Launch functionality +// to fail with an error: cap.ErrNoLaunch. If this value is false you +// have two choices with respect to the Launch functionality: +// +// 1) don't use cap.(*Launcher).Launch() +// 2) upgrade your Go toolchain to 1.10+ (ie., do this one). +const LaunchSupported = false + +// validatePA confirms that the pa.Sys entry is not incompatible with +// Launch. +func validatePA(pa *syscall.ProcAttr, chroot string) (bool, error) { + return false, ErrNoLaunch +} diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/cap/oslocks.go b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/oslocks.go new file mode 100644 index 0000000..9754020 --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/oslocks.go @@ -0,0 +1,51 @@ +// +build go1.10 + +package cap + +import "syscall" + +// LaunchSupported indicates that is safe to return from a locked +// OS Thread and have that OS Thread be terminated by the runtime. The +// Launch functionality really needs to rely on the fact that an +// excess of runtime.LockOSThread() vs. runtime.UnlockOSThread() calls +// in a returning go routine will cause the underlying locked OSThread +// to terminate. That feature was added to the Go runtime in version +// 1.10. +// +// See these bugs for the discussion and feature assumed by the code +// in this Launch() functionality: +// +// https://github.com/golang/go/issues/20395 +// https://github.com/golang/go/issues/20458 +// +// A value of false for this constant causes the Launch functionality +// to fail with an error: cap.ErrNoLaunch. If this value is false you +// have two choices with respect to the Launch functionality: +// +// 1) don't use cap.(*Launcher).Launch() +// 2) upgrade your Go toolchain to 1.10+ (ie., do this one). +const LaunchSupported = true + +// validatePA confirms that the pa.Sys entry is not incompatible with +// Launch and loads up the chroot value. +func validatePA(pa *syscall.ProcAttr, chroot string) (bool, error) { + s := pa.Sys + if s == nil { + if chroot == "" { + return false, nil + } + s = &syscall.SysProcAttr{ + Chroot: chroot, + } + pa.Sys = s + } else if s.Chroot != "" { + return false, ErrAmbiguousChroot + } + if s.Credential != nil { + return false, ErrAmbiguousIDs + } + if len(s.AmbientCaps) != 0 { + return false, ErrAmbiguousAmbient + } + return s != nil && s.Chroot != "", nil +} diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/cap/syscalls.go b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/syscalls.go new file mode 100644 index 0000000..6f311a8 --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/syscalls.go @@ -0,0 +1,121 @@ +package cap + +import ( + "runtime" + "sync" + "syscall" + + "kernel.org/pub/linux/libs/security/libcap/psx" +) + +// multisc provides syscalls overridable for testing purposes that +// support a single kernel security state for all OS threads. +// We use this version when we are cgo compiling because +// we need to manage the native C pthreads too. +var multisc = &syscaller{ + w3: psx.Syscall3, + w6: psx.Syscall6, + r3: syscall.RawSyscall, + r6: syscall.RawSyscall6, +} + +// singlesc provides a single threaded implementation. Users should +// take care to ensure the thread is locked and marked nogc. +var singlesc = &syscaller{ + w3: syscall.RawSyscall, + w6: syscall.RawSyscall6, + r3: syscall.RawSyscall, + r6: syscall.RawSyscall6, +} + +// launchState is used to track which variant of the write syscalls +// should execute. +type launchState int + +// these states are used to understand when a launch is in progress. +const ( + launchIdle launchState = iota + launchActive + launchBlocked +) + +// scwMu is used to fully serialize the write system calls. Note, this +// would generally not be necesary, but in the case of Launch we get +// into a situation where the launching thread is temporarily allowed +// to deviate from the kernel state of the rest of the runtime and +// allowing other threads to perform w* syscalls will potentially +// interfere with the launching process. In pure Go binaries, this +// will lead inevitably to a panic when the AllThreadsSyscall +// discovers inconsistent thread state. +// +// scwMu protects scwTIDs and scwState +var scwMu sync.Mutex + +// scwTIDs holds the thread IDs of the threads that are executing a +// launch it is empty when no launches are occurring. +var scwTIDs = make(map[int]bool) + +// scwState captures whether a launch is in progress or not. +var scwState = launchIdle + +// scwCond is used to announce when scwState changes to other +// goroutines waiting for it to change. +var scwCond = sync.NewCond(&scwMu) + +// scwSetState blocks until a launch state change between states from +// and to occurs. We use this for more context specific syscaller +// use. In the case that the caller is requesting a launchActive -> +// launchIdle transition they are declaring that tid is no longer +// launching. If another thread is also launching the call will +// complete, but the launchState will remain launchActive. +func scwSetState(from, to launchState, tid int) { + scwMu.Lock() + for scwState != from { + if scwState == launchActive && from == launchIdle && to == launchActive { + break // This "transition" is also allowed. + } + scwCond.Wait() + } + if from == launchIdle && to == launchActive { + scwTIDs[tid] = true + } else if from == launchActive && to == launchIdle { + delete(scwTIDs, tid) + if len(scwTIDs) != 0 { + to = from // not actually idle + } + } + scwState = to + scwCond.Broadcast() + scwMu.Unlock() +} + +// scwStateSC blocks until the current syscaller is available for +// writes, and then marks launchBlocked. Use scwSetState to perform +// the reverse transition (blocked->returned state value). +func scwStateSC() (launchState, *syscaller) { + sc := multisc + scwMu.Lock() + for { + if scwState == launchIdle { + break + } + runtime.LockOSThread() + if scwState == launchActive && scwTIDs[syscall.Gettid()] { + sc = singlesc + // note, we don't runtime.UnlockOSThread() + // here because we have no reason to ever + // allow this thread to return to normal use - + // we need it dead before we can return to the + // launchIdle state. + break + } + runtime.UnlockOSThread() + scwCond.Wait() + } + old := scwState + scwState = launchBlocked + scwCond.Broadcast() + scwMu.Unlock() + + return old, sc +} diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/cap/text.go b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/text.go new file mode 100644 index 0000000..cf11a2d --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/cap/text.go @@ -0,0 +1,325 @@ +package cap + +import ( + "bufio" + "errors" + "strconv" + "strings" +) + +// String converts a capability Value into its canonical text +// representation. +func (v Value) String() string { + name, ok := names[v] + if ok { + return name + } + // Un-named capabilities are referred to numerically (in decimal). + return strconv.Itoa(int(v)) +} + +// FromName converts a named capability Value to its binary +// representation. +func FromName(name string) (Value, error) { + startUp.Do(multisc.cInit) + v, ok := bits[name] + if ok { + if v >= Value(words*32) { + return 0, ErrBadValue + } + return v, nil + } + i, err := strconv.Atoi(name) + if err != nil { + return 0, err + } + if i >= 0 && i < int(words*32) { + return Value(i), nil + } + return 0, ErrBadValue +} + +const ( + eBin uint = (1 << Effective) + pBin = (1 << Permitted) + iBin = (1 << Inheritable) +) + +var combos = []string{"", "e", "p", "ep", "i", "ei", "ip", "eip"} + +// histo generates a histogram of flag state combinations. +func (c *Set) histo(bins []int, patterns []uint, from, limit Value) uint { + for v := from; v < limit; v++ { + b := uint(v & 31) + u, bit, err := bitOf(0, v) + if err != nil { + break + } + x := uint((c.flat[u][Effective]&bit)>>b) * eBin + x |= uint((c.flat[u][Permitted]&bit)>>b) * pBin + x |= uint((c.flat[u][Inheritable]&bit)>>b) * iBin + bins[x]++ + patterns[uint(v)] = x + } + // Note, in the loop, we use >= to pick the smallest value for + // m with the highest bin value. That is ties break towards + // m=0. + m := uint(7) + for t := m; t > 0; { + t-- + if bins[t] >= bins[m] { + m = t + } + } + return m +} + +// String converts a full capability Set into a single short readable +// string representation (which may contain spaces). See the +// cap.FromText() function for an explanation of its return values. +// +// Note (*cap.Set).String() may evolve to generate more compact +// strings representing the a given Set over time, but it should +// maintain compatibility with the libcap:cap_to_text() function for +// any given release. Further, it will always be an inverse of +// cap.FromText(). +func (c *Set) String() string { + if c == nil || len(c.flat) == 0 { + return "" + } + bins := make([]int, 8) + patterns := make([]uint, maxValues) + + c.mu.RLock() + defer c.mu.RUnlock() + + // Note, in order to have a *Set pointer, startUp.Do(cInit) + // must have been called which sets maxValues. + m := c.histo(bins, patterns, 0, Value(maxValues)) + + // Background state is the most popular of the named bits. + vs := []string{"=" + combos[m]} + for i := uint(8); i > 0; { + i-- + if i == m || bins[i] == 0 { + continue + } + var list []string + for j, p := range patterns { + if p != i { + continue + } + list = append(list, Value(j).String()) + } + x := strings.Join(list, ",") + var y, z string + if cf := i & ^m; cf != 0 { + op := "+" + if len(vs) == 1 && vs[0] == "=" { + // Special case "= foo+..." == "foo=...". + // Prefer because it + vs = nil + op = "=" + } + y = op + combos[cf] + } + if cf := m & ^i; cf != 0 { + z = "-" + combos[cf] + } + vs = append(vs, x+y+z) + } + + // The unnamed bits can only add to the above named ones since + // unnamed ones are always defaulted to lowered. + uBins := make([]int, 8) + uPatterns := make([]uint, 32*words) + c.histo(uBins, uPatterns, Value(maxValues), 32*Value(words)) + for i := uint(7); i > 0; i-- { + if uBins[i] == 0 { + continue + } + var list []string + for j, p := range uPatterns { + if p != i { + continue + } + list = append(list, Value(j).String()) + } + vs = append(vs, strings.Join(list, ",")+"+"+combos[i]) + } + + return strings.Join(vs, " ") +} + +// ErrBadText is returned if the text for a capability set cannot be parsed. +var ErrBadText = errors.New("bad text") + +// FromText converts the canonical text representation for a Set into +// a freshly allocated Set. +// +// The format follows the following pattern: a set of space separated +// sequences. Each sequence applies over the previous sequence to +// build up a Set. The format of a sequence is: +// +// [comma list of cap_values][[ops][flags]]* +// +// Examples: +// +// "all=ep" +// "cap_chown,cap_setuid=ip cap_setuid+e" +// "=p cap_setpcap-p+i" +// +// Here "all" refers to all named capabilities known to the hosting +// kernel, and "all" is assumed if no capabilities are listed before +// an "=". +// +// The ops values, "=", "+" and "-" imply "reset and raise", "raise" +// and "lower" respectively. The "e", "i" and "p" characters +// correspond to the capabilities of the corresponding Flag: "e" +// (Effective); "i" (Inheritable); "p" (Permitted). +// +// This syntax is overspecified and there are many ways of building +// the same final Set state. Any sequence that includes a '=' resets +// the accumulated state of all Flags ignoring earlier sequences. On +// each of the following lines we give three or more examples of ways +// to specify a common Set. The last entry on each line is the one +// generated by (*cap.Set).String() from that Set. +// +// "=p all+ei" "all=pie" "=pi all+e" "=eip" +// +// "cap_setuid=p cap_chown=i" "cap_chown=ip-p" "cap_chown=i" +// +// "cap_chown=-p" "all=" "cap_setuid=pie-pie" "=" +// +// Note: FromText() is tested at release time to completely match the +// import ability of the libcap:cap_from_text() function. +func FromText(text string) (*Set, error) { + c := NewSet() + scanner := bufio.NewScanner(strings.NewReader(text)) + scanner.Split(bufio.ScanWords) + chunks := 0 + for scanner.Scan() { + chunks++ + + // Parsing for xxx([-+=][eip]+)+ + t := scanner.Text() + i := strings.IndexAny(t, "=+-") + if i < 0 { + return nil, ErrBadText + } + var vs []Value + sep := t[i] + if vals := t[:i]; vals == "all" { + for v := Value(0); v < Value(maxValues); v++ { + vs = append(vs, v) + } + } else if vals != "" { + for _, name := range strings.Split(vals, ",") { + v, err := FromName(name) + if err != nil { + return nil, ErrBadText + } + vs = append(vs, v) + } + } else if sep != '=' { + if vals == "" { + // Only "=" supports ""=="all". + return nil, ErrBadText + } + } else if j := i + 1; j+1 < len(t) { + switch t[j] { + case '+': + sep = 'P' + i++ + case '-': + sep = 'M' + i++ + } + } + i++ + + // There are 5 ways to set: =, =+, =-, +, -. We call + // the 2nd and 3rd of these 'P' and 'M'. + + for { + // read [eip]+ setting flags. + var fE, fP, fI bool + for ok := true; ok && i < len(t); i++ { + switch t[i] { + case 'e': + fE = true + case 'i': + fI = true + case 'p': + fP = true + default: + ok = false + } + if !ok { + break + } + } + + if !(fE || fI || fP) { + if sep != '=' { + return nil, ErrBadText + } + } + + switch sep { + case '=', 'P', 'M', '+': + if sep != '+' { + c.Clear() + if sep == 'M' { + break + } + } + if keep := len(vs) == 0; keep { + if sep != '=' { + return nil, ErrBadText + } + c.forceFlag(Effective, fE) + c.forceFlag(Permitted, fP) + c.forceFlag(Inheritable, fI) + break + } + // =, + and P for specific values are left. + if fE { + c.SetFlag(Effective, true, vs...) + } + if fP { + c.SetFlag(Permitted, true, vs...) + } + if fI { + c.SetFlag(Inheritable, true, vs...) + } + case '-': + if fE { + c.SetFlag(Effective, false, vs...) + } + if fP { + c.SetFlag(Permitted, false, vs...) + } + if fI { + c.SetFlag(Inheritable, false, vs...) + } + } + + if i == len(t) { + break + } + + switch t[i] { + case '+', '-': + sep = t[i] + i++ + default: + return nil, ErrBadText + } + } + } + if chunks == 0 { + return nil, ErrBadText + } + return c, nil +} diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/psx/License b/vendor/kernel.org/pub/linux/libs/security/libcap/psx/License new file mode 100644 index 0000000..2645a87 --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/psx/License @@ -0,0 +1,396 @@ +Unless otherwise *explicitly* stated, the following text describes the +licensed conditions under which the contents of this libcap/psx release +may be used and distributed. + +The licensed conditions are one or the other of these two Licenses: + + - BSD 3-clause + - GPL v2.0 + +------------------------------------------------------------------------- +BSD 3-clause: +------------- + +Redistribution and use in source and binary forms of libcap/psx, with +or without modification, are permitted provided that the following +conditions are met: + +1. Redistributions of source code must retain any existing copyright + notice, and this entire permission notice in its entirety, + including the disclaimer of warranties. + +2. Redistributions in binary form must reproduce all prior and current + copyright notices, this list of conditions, and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +3. The name of any author may not be used to endorse or promote + products derived from this software without their specific prior + written permission. + +THIS SOFTWARE IS PROVIDED ``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 AUTHOR(S) 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. + +------------------------------------------------------------------------- +GPL v2.0: +--------- + +ALTERNATIVELY, this product may be distributed under the terms of the +GNU General Public License (v2.0 - see below), in which case the +provisions of the GNU GPL are required INSTEAD OF the above +restrictions. (This clause is necessary due to a potential conflict +between the GNU GPL and the restrictions contained in a BSD-style +copyright.) + +------------------------- +Full text of gpl-2.0.txt: +------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/psx/README b/vendor/kernel.org/pub/linux/libs/security/libcap/psx/README new file mode 100644 index 0000000..e4f9001 --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/psx/README @@ -0,0 +1,28 @@ +Package "psx" provides an API for invoking system calls in a way that +each system call is mirrored on all OS threads of the combined Go/CGo +runtime. Since the Go runtime treats OS threads as interchangeable, a +feature like this is needed to meaningfully change process privilege +(including dropping privilege) in a Go program running on Linux. This +package is required by: + + "kernel.org/pub/linux/libs/security/libcap/cap" + +When compiled CGO_ENABLED=0, the functionality requires go1.16+ to +build. That release of Go introduced syscall.AllThreadsSyscall*() +APIs. When compiled this way, the "psx" package functions +psx.Syscall3() and psx.Syscall6() are aliased to +syscall.AllThreadsSyscall() and syscall.AllThreadsSyscall6() +respectively. + +When compiled CGO_ENABLED=1, the functionality is implemented by C +code, [lib]psx, which is distributed with libcap. + +The official release announcement site for libcap and libpsx is: + + https://sites.google.com/site/fullycapable/ + +Like libcap/libpsx itself, the "psx" package is distributed with a +"you choose" License. Specifically: BSD three clause, or GPL2. See the +License file. + +Andrew G. Morgan diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/psx/doc.go b/vendor/kernel.org/pub/linux/libs/security/libcap/psx/doc.go new file mode 100644 index 0000000..384b0d3 --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/psx/doc.go @@ -0,0 +1,60 @@ +// Package psx provides support for system calls that are run +// simultanously on all threads under Linux. +// +// This property can be used to work around a historical lack of +// native Go support for such a feature. Something that is the subject +// of: +// +// https://github.com/golang/go/issues/1435 +// +// The package works differently depending on whether or not +// CGO_ENABLED is 0 or 1. +// +// In the former case, psx is a low overhead wrapper for the two +// native go calls: syscall.AllThreadsSyscall() and +// syscall.AllThreadsSyscall6() introduced in go1.16. We provide this +// wrapping to minimize client source code changes when compiling with +// or without CGo enabled. +// +// In the latter case, and toolchains prior to go1.16, it works via +// CGo wrappers for system call functions that call the C [lib]psx +// functions of these names. This ensures that the system calls +// execute simultaneously on all the pthreads of the Go (and CGo) +// combined runtime. +// +// With CGo, the psx support works in the following way: the pthread +// that is first asked to execute the syscall does so, and determines +// if it succeeds or fails. If it fails, it returns immediately +// without attempting the syscall on other pthreads. If the initial +// attempt succeeds, however, then the runtime is stopped in order for +// the same system call to be performed on all the remaining pthreads +// of the runtime. Once all pthreads have completed the syscall, the +// return codes are those obtained by the first pthread's invocation +// of the syscall. +// +// Note, there is no need to use this variant of syscall where the +// syscalls only read state from the kernel. However, since Go's +// runtime freely migrates code execution between pthreads, support of +// this type is required for any successful attempt to fully drop or +// modify the privilege of a running Go program under Linux. +// +// More info on how Linux privilege works and examples of using this +// package can be found here: +// +// https://sites.google.com/site/fullycapable +// +// WARNING: For older go toolchains (prior to go1.15), correct +// compilation of this package may require an extra workaround step: +// +// The workaround is to build with the following CGO_LDFLAGS_ALLOW in +// effect (here the syntax is that of bash for defining an environment +// variable): +// +// export CGO_LDFLAGS_ALLOW="-Wl,-?-wrap[=,][^-.@][^,]*" +// +// +// Copyright (c) 2019,20 Andrew G. Morgan +// +// The psx package is licensed with a (you choose) BSD 3-clause or +// GPL2. See LICENSE file for details. +package psx // import "kernel.org/pub/linux/libs/security/libcap/psx" diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/psx/go.mod b/vendor/kernel.org/pub/linux/libs/security/libcap/psx/go.mod new file mode 100644 index 0000000..c5f34b6 --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/psx/go.mod @@ -0,0 +1,3 @@ +module kernel.org/pub/linux/libs/security/libcap/psx + +go 1.11 diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/psx/psx.c b/vendor/kernel.org/pub/linux/libs/security/libcap/psx/psx.c new file mode 100644 index 0000000..12dbbc5 --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/psx/psx.c @@ -0,0 +1,644 @@ +/* + * Copyright (c) 2019-21 Andrew G Morgan + * + * This file contains a collection of routines that perform thread + * synchronization to ensure that a whole process is running as a + * single privilege entity - independent of the number of pthreads. + * + * The whole file would be unnecessary if glibc exported an explicit + * psx_syscall()-like function that leveraged the nptl:setxid + * mechanism to synchronize thread state over the whole process. + */ +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 199309L + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "psx_syscall.h" + +/* + * psx_load_syscalls() can be weakly defined in dependent libraries to + * provide a mechanism for a library to optionally leverage this psx + * mechanism. Specifically, when libcap calls psx_load_sycalls() it + * provides a weakly declared default that maps its system calls to + * the regular system call functions. However, when linked with psx, + * this function here overrides the syscalls to be the psx ones. + */ +void psx_load_syscalls(long int (**syscall_fn)(long int, + long int, long int, long int), + long int (**syscall6_fn)(long int, + long int, long int, long int, + long int, long int, long int)) +{ + *syscall_fn = psx_syscall3; + *syscall6_fn = psx_syscall6; +} + +/* + * type to keep track of registered threads. + */ +typedef struct registered_thread_s { + struct registered_thread_s *next, *prev; + pthread_t thread; + pthread_mutex_t mu; + int pending; + int gone; +} registered_thread_t; + +static pthread_once_t psx_tracker_initialized = PTHREAD_ONCE_INIT; + +typedef enum { + _PSX_IDLE = 0, + _PSX_SETUP = 1, + _PSX_SYSCALL = 2, + _PSX_CREATE = 3, + _PSX_INFORK = 4, + _PSX_EXITING = 5, +} psx_tracker_state_t; + +/* + * This global structure holds the global coordination state for + * libcap's psx_posix_syscall() support. + */ +static struct psx_tracker_s { + int has_forked; + + pthread_mutex_t state_mu; + pthread_cond_t cond; /* this is only used to wait on 'state' changes */ + psx_tracker_state_t state; + int initialized; + int psx_sig; + + struct { + long syscall_nr; + long arg1, arg2, arg3, arg4, arg5, arg6; + int six; + int active; + } cmd; + + struct sigaction sig_action; + struct sigaction chained_action; + registered_thread_t *root; +} psx_tracker; + +/* + * psx_action_key is used for thread local storage of the thread's + * registration. + */ +pthread_key_t psx_action_key; + +/* + * psx_do_registration called locked and creates a tracker entry for + * the current thread with a TLS specific key pointing at the threads + * specific tracker. + */ +static void *psx_do_registration(void) { + registered_thread_t *node = calloc(1, sizeof(registered_thread_t)); + pthread_mutex_init(&node->mu, NULL); + node->thread = pthread_self(); + pthread_setspecific(psx_action_key, node); + node->next = psx_tracker.root; + if (node->next) { + node->next->prev = node; + } + psx_tracker.root = node; + return node; +} + +/* + * psx_posix_syscall_actor performs the system call on the targeted + * thread and signals it is no longer pending. + */ +static void psx_posix_syscall_actor(int signum, siginfo_t *info, void *ignore) { + /* bail early if this isn't something we recognize */ + if (signum != psx_tracker.psx_sig || !psx_tracker.cmd.active || + info == NULL || info->si_code != SI_TKILL || info->si_pid != getpid()) { + if (psx_tracker.chained_action.sa_sigaction != 0) { + psx_tracker.chained_action.sa_sigaction(signum, info, ignore); + } + return; + } + + if (!psx_tracker.cmd.six) { + (void) syscall(psx_tracker.cmd.syscall_nr, + psx_tracker.cmd.arg1, + psx_tracker.cmd.arg2, + psx_tracker.cmd.arg3); + } else { + (void) syscall(psx_tracker.cmd.syscall_nr, + psx_tracker.cmd.arg1, + psx_tracker.cmd.arg2, + psx_tracker.cmd.arg3, + psx_tracker.cmd.arg4, + psx_tracker.cmd.arg5, + psx_tracker.cmd.arg6); + } + + /* + * This handler can only be called on registered threads which + * have had this specific defined at start-up. (But see the + * subsequent test.) + */ + registered_thread_t *ref = pthread_getspecific(psx_action_key); + if (ref) { + pthread_mutex_lock(&ref->mu); + ref->pending = 0; + pthread_mutex_unlock(&ref->mu); + } /* + * else thread must be dying and its psx_action_key has already + * been cleaned up. + */ +} + +/* + * Some forward declarations for the initialization + * psx_syscall_start() routine. + */ +static void _psx_prepare_fork(void); +static void _psx_fork_completed(void); +static void _psx_forked_child(void); +int __wrap_pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg); + +/* + * psx requires this function to be provided by the linkage wrapping. + */ +extern int __real_pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg); + +/* + * psx_confirm_sigaction reconfirms that the psx handler is the first + * handler to respond to the psx signal. It assumes that + * psx_tracker.psx_sig has been set. + */ +static void psx_confirm_sigaction(void) { + sigset_t mask, orig; + struct sigaction existing_sa; + + /* + * Block interrupts while potentially rewriting the handler. + */ + sigemptyset(&mask); + sigaddset(&mask, psx_tracker.psx_sig); + sigprocmask(SIG_BLOCK, &mask, &orig); + + sigaction(psx_tracker.psx_sig, NULL, &existing_sa); + if (existing_sa.sa_sigaction != psx_posix_syscall_actor) { + memcpy(&psx_tracker.chained_action, &existing_sa, sizeof(struct sigaction)); + psx_tracker.sig_action.sa_sigaction = psx_posix_syscall_actor; + sigemptyset(&psx_tracker.sig_action.sa_mask); + psx_tracker.sig_action.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART; + sigaction(psx_tracker.psx_sig, &psx_tracker.sig_action, NULL); + } + + sigprocmask(SIG_SETMASK, &orig, NULL); +} + +/* + * psx_syscall_start initializes the subsystem including initializing + * the mutex. + */ +static void psx_syscall_start(void) { + pthread_mutex_init(&psx_tracker.state_mu, NULL); + pthread_cond_init(&psx_tracker.cond, NULL); + pthread_key_create(&psx_action_key, NULL); + pthread_atfork(_psx_prepare_fork, _psx_fork_completed, _psx_forked_child); + + /* + * All sorts of things are assumed by Linux and glibc and/or musl + * about signal handlers and which can be blocked. Go has its own + * idiosyncrasies too. We tried SIGRTMAX until + * + * https://bugzilla.kernel.org/show_bug.cgi?id=210533 + * + * Our current strategy is to aggressively intercept SIGSYS. + */ + psx_tracker.psx_sig = SIGSYS; + + psx_confirm_sigaction(); + psx_do_registration(); // register the main thread. + + psx_tracker.initialized = 1; +} + +/* + * This is the only way this library globally locks. Note, this is not + * to be confused with psx_sig (interrupt) blocking - which is + * performed around thread creation and when the signal handler is + * being confirmed. + */ +static void psx_lock(void) +{ + pthread_once(&psx_tracker_initialized, psx_syscall_start); + pthread_mutex_lock(&psx_tracker.state_mu); +} + +/* + * This is the only way this library unlocks. + */ +static void psx_unlock(void) +{ + pthread_mutex_unlock(&psx_tracker.state_mu); +} + +/* + * under lock perform a state transition. + */ +static void psx_new_state(psx_tracker_state_t was, psx_tracker_state_t is) +{ + psx_lock(); + while (psx_tracker.state != was) { + pthread_cond_wait(&psx_tracker.cond, &psx_tracker.state_mu); + } + psx_tracker.state = is; + if (is == _PSX_IDLE) { + /* only announce newly idle states since that is all we wait for */ + pthread_cond_signal(&psx_tracker.cond); + } + psx_unlock(); +} + +long int psx_syscall3(long int syscall_nr, + long int arg1, long int arg2, long int arg3) { + return psx_syscall(syscall_nr, arg1, arg2, arg3); +} + +long int psx_syscall6(long int syscall_nr, + long int arg1, long int arg2, long int arg3, + long int arg4, long int arg5, long int arg6) { + return psx_syscall(syscall_nr, arg1, arg2, arg3, arg4, arg5, arg6); +} + +static void _psx_prepare_fork(void) { + /* + * obtain global lock - we don't want any syscalls while the fork + * is occurring since it may interfere with the preparation for + * the fork. + */ + psx_new_state(_PSX_IDLE, _PSX_INFORK); +} + +static void _psx_fork_completed(void) { + /* + * The only way we can get here is if state is _PSX_INFORK and was + * previously _PSX_IDLE. Now that the fork has completed, the + * parent can continue as if it hadn't happened - the forked child + * does not tie its security state to that of the parent process + * and threads. + * + * We don't strictly need to change the psx_tracker.state since we + * hold the mutex over the fork, but we do to make deadlock + * debugging easier. + */ + psx_new_state(_PSX_INFORK, _PSX_IDLE); +} + +static void _psx_forked_child(void) { + /* + * The only way we can get here is if state is _PSX_INFORK and was + * previously _PSX_IDLE. However, none of the registered threads + * exist in this newly minted child process, so we have to reset + * the tracking structure to avoid any confusion. We also scuttle + * any chance of the PSX API working on more than one thread in + * the child by leaving the state as _PSX_INFORK. We do support + * all psx_syscall()s by reverting to them being direct in the + * fork()ed child. + * + * We do this because the glibc man page for fork() suggests that + * only a subset of things will work post fork(). Specifically, + * only a "async-signal-safe functions (see signal- safety(7)) + * until such time as it calls execve(2)" can be relied upon. That + * man page suggests that you can't expect mutexes to work: "not + * async-signal-safe because it uses pthread_mutex_lock(3) + * internally.". + */ + registered_thread_t *next, *old_root; + old_root = psx_tracker.root; + psx_tracker.root = NULL; + + psx_tracker.has_forked = 1; + + for (; old_root; old_root = next) { + next = old_root->next; + memset(old_root, 0, sizeof(*old_root)); + free(old_root); + } +} + +/* + * called locked to unregister a node from the tracker. + */ +static void psx_do_unregister(registered_thread_t *node) { + if (psx_tracker.root == node) { + psx_tracker.root = node->next; + } + if (node->next) { + node->next->prev = node->prev; + } + if (node->prev) { + node->prev->next = node->next; + } + pthread_mutex_destroy(&node->mu); + memset(node, 0, sizeof(*node)); + free(node); +} + +typedef struct { + void *(*fn)(void *); + void *arg; + sigset_t sigbits; +} psx_starter_t; + +/* + * _psx_exiting is used to cleanup the node for the thread on its exit + * path. This is needed for musl libc: + * + * https://bugzilla.kernel.org/show_bug.cgi?id=208477 + * + * and likely wise for glibc too: + * + * https://sourceware.org/bugzilla/show_bug.cgi?id=12889 + */ +static void _psx_exiting(void *node) { + /* + * Until we are in the _PSX_EXITING state, we must not block the + * psx_sig interrupt for this dying thread. That is, until this + * exiting thread can set ref->gone to 1, this dying thread is + * still participating in the psx syscall distribution. + * + * See https://github.com/golang/go/issues/42494 for a situation + * where this code is called with psx_tracker.psx_sig blocked. + */ + sigset_t sigbit, orig_sigbits; + sigemptyset(&sigbit); + pthread_sigmask(SIG_UNBLOCK, &sigbit, &orig_sigbits); + sigaddset(&sigbit, psx_tracker.psx_sig); + pthread_sigmask(SIG_UNBLOCK, &sigbit, NULL); + + /* + * With psx_tracker.psx_sig unblocked we can wait until this + * thread can enter the _PSX_EXITING state. + */ + psx_new_state(_PSX_IDLE, _PSX_EXITING); + + /* + * We now indicate that this thread is no longer participating in + * the psx mechanism. + */ + registered_thread_t *ref = node; + pthread_mutex_lock(&ref->mu); + ref->gone = 1; + pthread_mutex_unlock(&ref->mu); + + /* + * At this point, we can restore the calling sigmask to whatever + * the caller thought was appropriate for a dying thread to have. + */ + pthread_sigmask(SIG_SETMASK, &orig_sigbits, NULL); + + /* + * Allow the rest of the psx system carry on as per normal. + */ + psx_new_state(_PSX_EXITING, _PSX_IDLE); +} + +/* + * _psx_start_fn is a trampoline for the intended start function, it + * is called blocked (_PSX_CREATE), but releases the block before + * calling starter->fn. Before releasing the block, the TLS specific + * attributes are initialized for use by the interrupt handler under + * the psx mutex, so it doesn't race with an interrupt received by + * this thread and the interrupt handler does not need to poll for + * that specific attribute to be present (which is problematic during + * thread shutdown). + */ +static void *_psx_start_fn(void *data) { + void *node = psx_do_registration(); + + psx_new_state(_PSX_CREATE, _PSX_IDLE); + + psx_starter_t *starter = data; + pthread_sigmask(SIG_SETMASK, &starter->sigbits, NULL); + void *(*fn)(void *) = starter->fn; + void *arg = starter->arg; + + memset(data, 0, sizeof(*starter)); + free(data); + + void *ret; + + pthread_cleanup_push(_psx_exiting, node); + ret = fn(arg); + pthread_cleanup_pop(1); + + return ret; +} + +/* + * __wrap_pthread_create is the wrapped destination of all regular + * pthread_create calls. + */ +int __wrap_pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg) { + psx_starter_t *starter = calloc(1, sizeof(psx_starter_t)); + if (starter == NULL) { + perror("failed at thread creation"); + exit(1); + } + starter->fn = start_routine; + starter->arg = arg; + /* + * Until we are in the _PSX_IDLE state and locked, we must not + * block the psx_sig interrupt for this parent thread. Arrange + * that parent thread and newly created one can restore signal + * mask. + */ + sigset_t sigbit, orig_sigbits; + sigemptyset(&sigbit); + pthread_sigmask(SIG_UNBLOCK, &sigbit, &starter->sigbits); + sigaddset(&sigbit, psx_tracker.psx_sig); + pthread_sigmask(SIG_UNBLOCK, &sigbit, &orig_sigbits); + + psx_new_state(_PSX_IDLE, _PSX_CREATE); + + /* + * until the child thread has been blessed with its own TLS + * specific attribute(s) we prevent either the parent thread or + * the new one from experiencing a PSX interrupt. + */ + pthread_sigmask(SIG_BLOCK, &sigbit, NULL); + + int ret = __real_pthread_create(thread, attr, _psx_start_fn, starter); + if (ret == -1) { + psx_new_state(_PSX_CREATE, _PSX_IDLE); + memset(starter, 0, sizeof(*starter)); + free(starter); + } /* else unlock happens in _psx_start_fn */ + + /* the parent can once again receive psx interrupt signals */ + pthread_sigmask(SIG_SETMASK, &orig_sigbits, NULL); + + return ret; +} + +/* + * __psx_immediate_syscall does one syscall using the current + * process. + */ +static long int __psx_immediate_syscall(long int syscall_nr, + int count, long int *arg) { + psx_tracker.cmd.syscall_nr = syscall_nr; + psx_tracker.cmd.arg1 = count > 0 ? arg[0] : 0; + psx_tracker.cmd.arg2 = count > 1 ? arg[1] : 0; + psx_tracker.cmd.arg3 = count > 2 ? arg[2] : 0; + + if (count > 3) { + psx_tracker.cmd.six = 1; + psx_tracker.cmd.arg4 = arg[3]; + psx_tracker.cmd.arg5 = count > 4 ? arg[4] : 0; + psx_tracker.cmd.arg6 = count > 5 ? arg[5] : 0; + return syscall(syscall_nr, + psx_tracker.cmd.arg1, + psx_tracker.cmd.arg2, + psx_tracker.cmd.arg3, + psx_tracker.cmd.arg4, + psx_tracker.cmd.arg5, + psx_tracker.cmd.arg6); + } + + psx_tracker.cmd.six = 0; + return syscall(syscall_nr, psx_tracker.cmd.arg1, + psx_tracker.cmd.arg2, psx_tracker.cmd.arg3); +} + +/* + * __psx_syscall performs the syscall on the current thread and if no + * error is detected it ensures that the syscall is also performed on + * all (other) registered threads. The return code is the value for + * the first invocation. It uses a trick to figure out how many + * arguments the user has supplied. The other half of the trick is + * provided by the macro psx_syscall() in the + * file. The trick is the 7th optional argument (8th over all) to + * __psx_syscall is the count of arguments supplied to psx_syscall. + * + * User: + * psx_syscall(nr, a, b); + * Expanded by macro to: + * __psx_syscall(nr, a, b, 6, 5, 4, 3, 2, 1, 0); + * The eighth arg is now ------------------------------------^ + */ +long int __psx_syscall(long int syscall_nr, ...) { + long int arg[7]; + int i; + + va_list aptr; + va_start(aptr, syscall_nr); + for (i = 0; i < 7; i++) { + arg[i] = va_arg(aptr, long int); + } + va_end(aptr); + + int count = arg[6]; + if (count < 0 || count > 6) { + errno = EINVAL; + return -1; + } + + if (psx_tracker.has_forked) { + return __psx_immediate_syscall(syscall_nr, count, arg); + } + + psx_new_state(_PSX_IDLE, _PSX_SETUP); + psx_confirm_sigaction(); + + long int ret; + + ret = __psx_immediate_syscall(syscall_nr, count, arg); + if (ret == -1 || !psx_tracker.initialized) { + psx_new_state(_PSX_SETUP, _PSX_IDLE); + goto defer; + } + + int restore_errno = errno; + + psx_new_state(_PSX_SETUP, _PSX_SYSCALL); + psx_tracker.cmd.active = 1; + + pthread_t self = pthread_self(); + registered_thread_t *next = NULL, *ref; + + psx_lock(); + for (ref = psx_tracker.root; ref; ref = next) { + next = ref->next; + if (ref->thread == self) { + continue; + } + pthread_mutex_lock(&ref->mu); + ref->pending = 1; + int gone = ref->gone; + if (!gone) { + gone = pthread_kill(ref->thread, psx_tracker.psx_sig) != 0; + } + pthread_mutex_unlock(&ref->mu); + if (!gone) { + continue; + } + /* + * need to remove invalid thread id from linked list + */ + psx_do_unregister(ref); + } + psx_unlock(); + + for (;;) { + int waiting = 0; + psx_lock(); + for (ref = psx_tracker.root; ref; ref = next) { + next = ref->next; + if (ref->thread == self) { + continue; + } + + pthread_mutex_lock(&ref->mu); + int pending = ref->pending; + int gone = ref->gone; + if (pending && !gone) { + gone = (pthread_kill(ref->thread, 0) != 0); + } + pthread_mutex_unlock(&ref->mu); + if (!gone) { + waiting += pending; + continue; + } + /* + * need to remove invalid thread id from linked list + */ + psx_do_unregister(ref); + } + psx_unlock(); + if (!waiting) { + break; + } + sched_yield(); + } + + errno = restore_errno; + psx_tracker.cmd.active = 0; + psx_new_state(_PSX_SYSCALL, _PSX_IDLE); + +defer: + return ret; +} diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/psx/psx.go b/vendor/kernel.org/pub/linux/libs/security/libcap/psx/psx.go new file mode 100644 index 0000000..77648e2 --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/psx/psx.go @@ -0,0 +1,19 @@ +// +build linux,!cgo +// +build go1.16 + +package psx // import "kernel.org/pub/linux/libs/security/libcap/psx" + +import "syscall" + +// Documentation for these functions are provided in the psx_cgo.go +// file. + +//go:uintptrescapes +func Syscall3(syscallnr, arg1, arg2, arg3 uintptr) (uintptr, uintptr, syscall.Errno) { + return syscall.AllThreadsSyscall(syscallnr, arg1, arg2, arg3) +} + +//go:uintptrescapes +func Syscall6(syscallnr, arg1, arg2, arg3, arg4, arg5, arg6 uintptr) (uintptr, uintptr, syscall.Errno) { + return syscall.AllThreadsSyscall6(syscallnr, arg1, arg2, arg3, arg4, arg5, arg6) +} diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/psx/psx_cgo.go b/vendor/kernel.org/pub/linux/libs/security/libcap/psx/psx_cgo.go new file mode 100644 index 0000000..26aa15a --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/psx/psx_cgo.go @@ -0,0 +1,79 @@ +// +build linux,cgo + +package psx // import "kernel.org/pub/linux/libs/security/libcap/psx" + +import ( + "runtime" + "syscall" +) + +// #cgo LDFLAGS: -lpthread -Wl,-wrap,pthread_create +// +// #include +// #include "psx_syscall.h" +// +// long __errno_too(long set_errno) { +// long v = errno; +// if (set_errno >= 0) { +// errno = set_errno; +// } +// return v; +// } +import "C" + +// setErrno returns the current C.errno value and, if v >= 0, sets the +// CGo errno for a random pthread to value v. If you want some +// consistency, this needs to be called from runtime.LockOSThread() +// code. This function is only defined for testing purposes. The psx.c +// code should properly handle the case that a non-zero errno is saved +// and restored independently of what these Syscall[36]() functions +// observe. +func setErrno(v int) int { + return int(C.__errno_too(C.long(v))) +} + +//go:uintptrescapes + +// Syscall3 performs a 3 argument syscall. Syscall3 differs from +// syscall.[Raw]Syscall() insofar as it is simultaneously executed on +// every thread of the combined Go and CGo runtimes. It works +// differently depending on whether CGO_ENABLED is 1 or 0 at compile +// time. +// +// If CGO_ENABLED=1 it uses the libpsx function C.psx_syscall3(). +// +// If CGO_ENABLED=0 it redirects to the go1.16+ +// syscall.AllThreadsSyscall() function. +func Syscall3(syscallnr, arg1, arg2, arg3 uintptr) (uintptr, uintptr, syscall.Errno) { + // We lock to the OSThread here because we may need errno to + // be the one for this thread. + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + v := C.psx_syscall3(C.long(syscallnr), C.long(arg1), C.long(arg2), C.long(arg3)) + var errno syscall.Errno + if v < 0 { + errno = syscall.Errno(C.__errno_too(-1)) + } + return uintptr(v), uintptr(v), errno +} + +//go:uintptrescapes + +// Syscall6 performs a 6 argument syscall on every thread of the +// combined Go and CGo runtimes. Other than the number of syscall +// arguments, its behavior is identical to that of Syscall3() - see +// above for the full documentation. +func Syscall6(syscallnr, arg1, arg2, arg3, arg4, arg5, arg6 uintptr) (uintptr, uintptr, syscall.Errno) { + // We lock to the OSThread here because we may need errno to + // be the one for this thread. + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + v := C.psx_syscall6(C.long(syscallnr), C.long(arg1), C.long(arg2), C.long(arg3), C.long(arg4), C.long(arg5), C.long(arg6)) + var errno syscall.Errno + if v < 0 { + errno = syscall.Errno(C.__errno_too(-1)) + } + return uintptr(v), uintptr(v), errno +} diff --git a/vendor/kernel.org/pub/linux/libs/security/libcap/psx/psx_syscall.h b/vendor/kernel.org/pub/linux/libs/security/libcap/psx/psx_syscall.h new file mode 100644 index 0000000..4aacfab --- /dev/null +++ b/vendor/kernel.org/pub/linux/libs/security/libcap/psx/psx_syscall.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2019 Andrew G. Morgan + * + * This header, and the -lpsx library, provide a number of things to + * support POSIX semantics for syscalls associated with the pthread + * library. Linking this code is tricky and is done as follows: + * + * ld ... -lpsx -lpthread --wrap=pthread_create + * or, gcc ... -lpsx -lpthread -Wl,-wrap,pthread_create + * + * glibc provides a subset of this functionality natively through the + * nptl:setxid mechanism and could implement psx_syscall() directly + * using that style of functionality but, as of 2019-11-30, the setxid + * mechanism is limited to 9 specific set*() syscalls that do not + * support the syscall6 API (needed for prctl functions and the ambient + * capabilities set for example). + */ + +#ifndef _SYS_PSX_SYSCALL_H +#define _SYS_PSX_SYSCALL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + * psx_syscall performs the specified syscall on all psx registered + * threads. The mechanism by which this occurs is much less efficient + * than a standard system call on Linux, so it should only be used + * when POSIX semantics are required to change process relevant + * security state. + * + * Glibc has native support for POSIX semantics on setgroups() and the + * 8 set*[gu]id() functions. So, there is no need to use psx_syscall() + * for these calls. This call exists for all the other system calls + * that need to maintain parity on all pthreads of a program. + * + * Some macrology is used to allow the caller to provide only as many + * arguments as needed, thus psx_syscall() cannot be used as a + * function pointer. For those situations, we define psx_syscall3() + * and psx_syscall6(). + */ +#define psx_syscall(syscall_nr, ...) \ + __psx_syscall(syscall_nr, __VA_ARGS__, (long int) 6, (long int) 5, \ + (long int) 4, (long int) 3, (long int) 2, \ + (long int) 1, (long int) 0) +long int __psx_syscall(long int syscall_nr, ...); +long int psx_syscall3(long int syscall_nr, + long int arg1, long int arg2, long int arg3); +long int psx_syscall6(long int syscall_nr, + long int arg1, long int arg2, long int arg3, + long int arg4, long int arg5, long int arg6); + +/* + * This function should be used by systems to obtain pointers to the + * two syscall functions provided by the PSX library. A linkage trick + * is to define this function as weak in a library that can optionally + * use libpsx and then, should the caller link -lpsx, that library can + * implicitly use these POSIX semantics syscalls. See libcap for an + * example of this useage. + */ +void psx_load_syscalls(long int (**syscall_fn)(long int, + long int, long int, long int), + long int (**syscall6_fn)(long int, + long int, long int, long int, + long int, long int, long int)); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_PSX_SYSCALL_H */ diff --git a/vendor/modules.txt b/vendor/modules.txt index 38c8b6a..be08f68 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -62,3 +62,8 @@ gvisor.dev/gvisor/pkg/tcpip/transport/tcp gvisor.dev/gvisor/pkg/tcpip/transport/tcpconntrack gvisor.dev/gvisor/pkg/tcpip/transport/udp gvisor.dev/gvisor/pkg/waiter +# kernel.org/pub/linux/libs/security/libcap/cap v1.2.51 +## explicit +kernel.org/pub/linux/libs/security/libcap/cap +# kernel.org/pub/linux/libs/security/libcap/psx v1.2.51 +kernel.org/pub/linux/libs/security/libcap/psx