1 /*************************************************************************** 2 * 3 * util_helper.c - HAL utilities for helper (as e.g. prober/addons) et al. 4 * 5 * Copyright (C) 2006 David Zeuthen, <david@fubar.dk> 6 * 7 * Licensed under the Academic Free License version 2.1 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 * 23 **************************************************************************/ 24 25 #ifdef HAVE_CONFIG_H 26 # include <config.h> 27 #endif 28 29 #include <grp.h> 30 #include <stdarg.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <sys/time.h> 34 #include <time.h> 35 #include <pwd.h> 36 #include <unistd.h> 37 38 #include "logger.h" 39 40 #include "util_helper.h" 41 42 #ifdef __linux__ 43 extern char **environ; 44 #endif 45 46 static char **argv_buffer = NULL; 47 static size_t argv_size = 0; 48 49 #ifdef sun 50 #include <priv.h> 51 void 52 drop_privileges(int keep_auxgroups) 53 { 54 priv_set_t *pPrivSet; 55 56 /* 57 * Start with the 'basic' privilege set and then remove any 58 * of the 'basic' privileges that will not be needed. 59 */ 60 if ((pPrivSet = priv_allocset()) == NULL) { 61 return; 62 } 63 64 /* 65 * Establish the basic set of privileges. 66 * Note: fork/exec required for libdevinfo devlink 67 * interfaces are included in the basic set. 68 */ 69 priv_basicset(pPrivSet); 70 71 /* Clear privileges we will not need from the 'basic' set */ 72 (void) priv_delset(pPrivSet, PRIV_FILE_LINK_ANY); 73 (void) priv_delset(pPrivSet, PRIV_PROC_INFO); 74 (void) priv_delset(pPrivSet, PRIV_PROC_SESSION); 75 76 /* for sysevent need to be root and have this privilege */ 77 (void) priv_addset(pPrivSet, PRIV_SYS_CONFIG); 78 79 /* need proc_audit privilege */ 80 (void) priv_addset(pPrivSet, PRIV_PROC_AUDIT); 81 82 /* Set the permitted privilege set. */ 83 (void) setppriv(PRIV_SET, PRIV_PERMITTED, pPrivSet); 84 85 /* Set the limit privilege set. */ 86 (void) setppriv(PRIV_SET, PRIV_LIMIT, pPrivSet); 87 88 priv_freeset(pPrivSet); 89 } 90 #else /* !sun */ 91 92 /** Drop root privileges: Set the running user id to HAL_USER and 93 * group to HAL_GROUP, and optionally retain auxiliary groups of HAL_USER. 94 */ 95 void 96 drop_privileges (int keep_auxgroups) 97 { 98 struct passwd *pw = NULL; 99 struct group *gr = NULL; 100 101 /* determine user id */ 102 pw = getpwnam (HAL_USER); 103 if (!pw) { 104 HAL_DEBUG (("drop_privileges: user " HAL_USER " does not exist")); 105 exit (-1); 106 } 107 108 /* determine primary group id */ 109 gr = getgrnam (HAL_GROUP); 110 if (!gr) { 111 HAL_DEBUG (("drop_privileges: group " HAL_GROUP " does not exist")); 112 exit (-1); 113 } 114 115 if (keep_auxgroups) { 116 if (initgroups (HAL_USER, gr->gr_gid)) { 117 HAL_DEBUG(("drop_privileges: could not initialize groups")); 118 exit (-1); 119 } 120 } 121 122 if (setgid (gr->gr_gid)) { 123 HAL_DEBUG (("drop_privileges: could not set group id")); 124 exit (-1); 125 } 126 127 if (setuid (pw->pw_uid)) { 128 HAL_DEBUG (("drop_privileges: could not set user id")); 129 exit (-1); 130 } 131 } 132 #endif /* !sun */ 133 134 void 135 hal_set_proc_title_init (int argc, char *argv[]) 136 { 137 #ifdef __linux__ 138 unsigned int i; 139 char **new_environ, *endptr; 140 141 /* This code is really really ugly. We make some memory layout 142 * assumptions and reuse the environment array as memory to store 143 * our process title in */ 144 145 for (i = 0; environ[i] != NULL; i++) 146 ; 147 148 endptr = i ? environ[i-1] + strlen (environ[i-1]) : argv[argc-1] + strlen (argv[argc-1]); 149 150 argv_buffer = argv; 151 argv_size = endptr - argv_buffer[0]; 152 153 /* Make a copy of environ */ 154 155 new_environ = malloc (sizeof(char*) * (i + 1)); 156 for (i = 0; environ[i] != NULL; i++) 157 new_environ[i] = strdup (environ[i]); 158 new_environ[i] = NULL; 159 160 environ = new_environ; 161 #endif 162 } 163 164 /* this code borrowed from avahi-daemon's setproctitle.c (LGPL v2) */ 165 void 166 hal_set_proc_title (const char *format, ...) 167 { 168 #ifdef __linux__ 169 size_t len; 170 va_list ap; 171 172 if (argv_buffer == NULL) 173 goto out; 174 175 va_start (ap, format); 176 vsnprintf (argv_buffer[0], argv_size, format, ap); 177 va_end (ap); 178 179 len = strlen (argv_buffer[0]); 180 181 memset (argv_buffer[0] + len, 0, argv_size - len); 182 argv_buffer[1] = NULL; 183 out: 184 ; 185 #endif 186 } 187 188