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