github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/cmd/libsnap-confine-private/privs.c (about) 1 /* 2 * Copyright (C) 2017 Canonical Ltd 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 3 as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 * 16 */ 17 18 #include "privs.h" 19 20 #define _GNU_SOURCE 21 22 #include <unistd.h> 23 24 #include <grp.h> 25 #include <stdbool.h> 26 #include <sys/capability.h> 27 #include <sys/types.h> 28 #include <unistd.h> 29 30 #include "utils.h" 31 32 static bool sc_has_capability(const char *cap_name) 33 { 34 // Lookup capability with the given name. 35 cap_value_t cap; 36 if (cap_from_name(cap_name, &cap) < 0) { 37 die("cannot resolve capability name %s", cap_name); 38 } 39 // Get the capability state of the current process. 40 cap_t caps; 41 if ((caps = cap_get_proc()) == NULL) { 42 die("cannot obtain capability state (cap_get_proc)"); 43 } 44 // Read the effective value of the flag we're dealing with 45 cap_flag_value_t cap_flags_value; 46 if (cap_get_flag(caps, cap, CAP_EFFECTIVE, &cap_flags_value) < 0) { 47 cap_free(caps); // don't bother checking, we die anyway. 48 die("cannot obtain value of capability flag (cap_get_flag)"); 49 } 50 // Free the representation of the capability state of the current process. 51 if (cap_free(caps) < 0) { 52 die("cannot free capability flag (cap_free)"); 53 } 54 // Check if the effective bit of the capability is set. 55 return cap_flags_value == CAP_SET; 56 } 57 58 void sc_privs_drop(void) 59 { 60 gid_t gid = getgid(); 61 uid_t uid = getuid(); 62 63 // Drop extra group membership if we can. 64 if (sc_has_capability("cap_setgid")) { 65 gid_t gid_list[1] = { gid }; 66 if (setgroups(1, gid_list) < 0) { 67 die("cannot set supplementary group identifiers"); 68 } 69 } 70 // Switch to real group ID 71 if (setgid(getgid()) < 0) { 72 die("cannot set group identifier to %d", gid); 73 } 74 // Switch to real user ID 75 if (setuid(getuid()) < 0) { 76 die("cannot set user identifier to %d", uid); 77 } 78 }