1 /*** 2 This file is part of avahi. 3 4 avahi is free software; you can redistribute it and/or modify it 5 under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 2.1 of the 7 License, or (at your option) any later version. 8 9 avahi is distributed in the hope that it will be useful, but WITHOUT 10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 11 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General 12 Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public 15 License along with avahi; if not, write to the Free Software 16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 17 USA. 18 ***/ 19 20 #ifdef HAVE_CONFIG_H 21 #include <config.h> 22 #endif 23 24 #include <sys/types.h> 25 #include <assert.h> 26 #include <errno.h> 27 #include <string.h> 28 #include <sys/capability.h> 29 #include <sys/prctl.h> 30 31 #include <avahi-core/log.h> 32 33 #include "caps.h" 34 35 int avahi_caps_reduce(void) { 36 int ret = 0; 37 cap_t caps; 38 static cap_value_t cap_values[] = { CAP_SYS_CHROOT, CAP_SETUID, CAP_SETGID }; 39 40 /* Let's reduce our caps to the minimum set and tell Linux to keep 41 * them across setuid(). This is called before we drop 42 * privileges. */ 43 44 caps = cap_init(); 45 assert(caps); 46 cap_clear(caps); 47 48 cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_values, CAP_SET); 49 cap_set_flag(caps, CAP_PERMITTED, 3, cap_values, CAP_SET); 50 51 if (cap_set_proc(caps) < 0) { 52 avahi_log_error("cap_set_proc() failed: %s", strerror(errno)); 53 ret = -1; 54 } 55 cap_free(caps); 56 57 /* Retain capabilities across setuid() */ 58 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) { 59 avahi_log_error("prctl(PR_SET_KEEPCAPS) failed: %s", strerror(errno)); 60 ret = -1; 61 } 62 63 return ret; 64 } 65 66 int avahi_caps_reduce2(void) { 67 int ret = 0; 68 cap_t caps; 69 static cap_value_t cap_values[] = { CAP_SYS_CHROOT }; 70 71 /* Reduce our caps to the bare minimum and tell Linux not to keep 72 * them across setuid(). This is called after we drop 73 * privileges. */ 74 75 /* No longer retain caps across setuid() */ 76 if (prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) < 0) { 77 avahi_log_error("prctl(PR_SET_KEEPCAPS) failed: %s", strerror(errno)); 78 ret = -1; 79 } 80 81 caps = cap_init(); 82 assert(caps); 83 cap_clear(caps); 84 85 /* setuid() zeroed our effective caps, let's get them back */ 86 cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_values, CAP_SET); 87 cap_set_flag(caps, CAP_PERMITTED, 1, cap_values, CAP_SET); 88 89 if (cap_set_proc(caps) < 0) { 90 avahi_log_error("cap_set_proc() failed: %s", strerror(errno)); 91 ret = -1; 92 } 93 cap_free(caps); 94 95 return ret; 96 } 97 98 int avahi_caps_drop_all(void) { 99 cap_t caps; 100 int ret = 0; 101 102 /* Drop all capabilities and turn ourselves into a normal user process */ 103 104 caps = cap_init(); 105 assert(caps); 106 cap_clear(caps); 107 108 if (cap_set_proc(caps) < 0) { 109 avahi_log_error("cap_set_proc() failed: %s", strerror(errno)); 110 ret = -1; 111 } 112 cap_free(caps); 113 114 return ret; 115 } 116