/[path-sandbox]/trunk/sandbox_futils.c
Gentoo

Contents of /trunk/sandbox_futils.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 97 - (hide annotations) (download) (as text)
Fri May 13 12:52:10 2005 UTC (13 years, 3 months ago) by azarah
File MIME type: text/x-csrc
File size: 12630 byte(s)
Add get_sandbox_debug_log(), and use it (add behaviour similar to SANDBOX_LOG
if already exported when sandbox started).  Fix get_sandbox_log() and new
get_sandbox_debug_log() to not use already exported environment variables if
they have '/' in them.  Use snprintf()'s instead of strncpy()'s.  More
SB_PATH_MAX fixes.

1 ferringb 2 /*
2     * Copyright (C) 2002 Brad House <brad@mainstreetsoftworks.com>
3     * Distributed under the terms of the GNU General Public License, v2 or later
4     * Author: Brad House <brad@mainstreetsoftworks.com>
5     *
6     * $Header$
7     *
8     */
9    
10     #include <errno.h>
11     #include <fcntl.h>
12     #include <signal.h>
13     #include <stdio.h>
14     #include <stdlib.h>
15     #include <limits.h>
16     #include <string.h>
17     #include <stdarg.h>
18     #include <sys/file.h>
19     #include <sys/stat.h>
20     #include <sys/time.h>
21     #include <sys/types.h>
22     #include <sys/resource.h>
23     #include <sys/wait.h>
24     #include <unistd.h>
25     #include <fcntl.h>
26    
27     #include <grp.h>
28     #include <pwd.h>
29    
30     #include "sandbox.h"
31 ferringb 13 #include "config.h"
32 ferringb 2
33     /* BEGIN Prototypes */
34 azarah 43 SB_STATIC int file_security_check(char *filename);
35 ferringb 2 /* END Prototypes */
36    
37     /* glibc modified getcwd() functions */
38 azarah 43 SB_STATIC char *egetcwd(char *, size_t);
39 ferringb 2
40 azarah 43 SB_STATIC char *get_sandbox_path(char *argv0)
41 ferringb 2 {
42 azarah 92 char path[SB_PATH_MAX];
43 ferringb 2
44     memset(path, 0, sizeof(path));
45     /* ARGV[0] specifies full path */
46     if (argv0[0] == '/') {
47 azarah 30 strncpy(path, argv0, sizeof(path) - 1);
48 ferringb 2
49     /* ARGV[0] specifies relative path */
50     } else {
51 azarah 92 if (-1 != readlink("/proc/self/exe", path, sizeof(path)))
52     path[sizeof(path) - 1] = '\0';
53     else
54     path[0] = '\0';
55 ferringb 2 }
56    
57     /* Return just directory */
58     return (sb_dirname(path));
59     }
60    
61 azarah 43 SB_STATIC char *get_sandbox_lib(char *sb_path)
62 ferringb 2 {
63 azarah 92 char path[SB_PATH_MAX];
64 ferringb 2
65     #ifdef SB_HAVE_64BIT_ARCH
66 azarah 30 snprintf(path, sizeof(path), "%s", LIB_NAME);
67 ferringb 2 #else
68 azarah 30 snprintf(path, sizeof(path), "%s/%s", LIBSANDBOX_PATH, LIB_NAME);
69 ferringb 2 if (file_exist(path, 0) <= 0) {
70     snprintf(path, sizeof(path), "%s%s", sb_path, LIB_NAME);
71     }
72     #endif
73     return (strdup(path));
74     }
75    
76 azarah 43 SB_STATIC char *get_sandbox_pids_file(void)
77 ferringb 2 {
78     if (0 < getenv("SANDBOX_PIDS_FILE")) {
79     return (strdup(getenv("SANDBOX_PIDS_FILE")));
80     }
81     return (strdup(PIDS_FILE));
82     }
83    
84 azarah 43 SB_STATIC char *get_sandbox_rc(char *sb_path)
85 ferringb 2 {
86 azarah 92 char path[SB_PATH_MAX];
87 ferringb 2
88 ferringb 13 snprintf(path, sizeof(path), "%s/%s", SANDBOX_BASHRC_PATH, BASHRC_NAME);
89 ferringb 2 if (file_exist(path, 0) <= 0) {
90     snprintf(path, sizeof(path), "%s%s", sb_path, BASHRC_NAME);
91     }
92     return (strdup(path));
93     }
94    
95 azarah 43 SB_STATIC char *get_sandbox_log()
96 ferringb 2 {
97 azarah 92 char path[SB_PATH_MAX];
98 ferringb 2 char *sandbox_log_env = NULL;
99    
100 azarah 97 sandbox_log_env = getenv(ENV_SANDBOX_LOG);
101    
102 ferringb 2 /* THIS CHUNK BREAK THINGS BY DOING THIS:
103     * SANDBOX_LOG=/tmp/sandbox-app-admin/superadduser-1.0.7-11063.log
104     */
105 azarah 97 if ((NULL != sandbox_log_env) &&
106     (NULL != strchr(sandbox_log_env, '/')))
107     sandbox_log_env = NULL;
108 ferringb 2
109 azarah 30 snprintf(path, sizeof(path) - 1, "%s%s%s%d%s", LOG_FILE_PREFIX,
110     (sandbox_log_env == NULL ? "" : sandbox_log_env),
111     (sandbox_log_env == NULL ? "" : "-"), getpid(), LOG_FILE_EXT);
112 ferringb 2 return (strdup(path));
113     }
114    
115 azarah 97 SB_STATIC char *get_sandbox_debug_log()
116     {
117     char path[SB_PATH_MAX];
118     char *sandbox_debug_log_env = NULL;
119    
120     sandbox_debug_log_env = getenv(ENV_SANDBOX_DEBUG_LOG);
121    
122     /* THIS CHUNK BREAK THINGS BY DOING THIS:
123     * SANDBOX_DEBUG_LOG=/tmp/sandbox-app-admin/superadduser-1.0.7-11063.log
124     */
125     if ((NULL != sandbox_debug_log_env) &&
126     (NULL != strchr(sandbox_debug_log_env, '/')))
127     sandbox_debug_log_env = NULL;
128    
129     snprintf(path, sizeof(path) - 1, "%sdebug-%s%s%d%s", LOG_FILE_PREFIX,
130     (sandbox_debug_log_env == NULL ? "" : sandbox_debug_log_env),
131     (sandbox_debug_log_env == NULL ? "" : "-"), getpid(), LOG_FILE_EXT);
132     return (strdup(path));
133     }
134    
135 ferringb 2 /* Obtain base directory name. Do not allow trailing / */
136 azarah 43 SB_STATIC char *sb_dirname(const char *path)
137 ferringb 2 {
138     char *ret = NULL;
139     char *ptr = NULL;
140     int loc = 0, i;
141     int cut_len = -1;
142    
143     /* don't think NULL will ever be passed, but just in case */
144     if (NULL == path)
145     return (strdup("."));
146    
147     /* Grab pointer to last slash */
148     ptr = strrchr(path, '/');
149     if (NULL == ptr) {
150     return (strdup("."));
151     }
152    
153     /* decimal location of pointer */
154     loc = ptr - path;
155    
156     /* Remove any trailing slash */
157     for (i = loc - 1; i >= 0; i--) {
158     if (path[i] != '/') {
159 azarah 30 cut_len = i + 1; /* make cut_len the length of the string to keep */
160 ferringb 2 break;
161     }
162     }
163    
164     /* It could have been just a plain /, return a 1byte 0 filled string */
165     if (-1 == cut_len)
166     return (strdup(""));
167    
168     /* Allocate memory, and return the directory */
169 azarah 30 ret = (char *)malloc((cut_len + 1) * sizeof(char));
170 ferringb 2 memcpy(ret, path, cut_len);
171     ret[cut_len] = 0;
172    
173     return (ret);
174     }
175    
176     /*
177 azarah 43 SB_STATIC char* dirname(const char* path)
178 ferringb 2 {
179     char* base = NULL;
180     unsigned int length = 0;
181    
182     base = strrchr(path, '/');
183     if (NULL == base)
184     {
185     return strdup(".");
186     }
187     while (base > path && *base == '/')
188     {
189     base--;
190     }
191     length = (unsigned int) 1 + base - path;
192    
193     base = malloc(sizeof(char)*(length+1));
194     memmove(base, path, length);
195     base[length] = 0;
196    
197     return base;
198     }*/
199    
200     /* Convert text (string) modes to integer values */
201 azarah 43 SB_STATIC int file_getmode(char *mode)
202 ferringb 2 {
203     int mde = 0;
204     if (0 == strcasecmp(mode, "r+")) {
205     mde = O_RDWR | O_CREAT;
206     } else if (0 == strcasecmp(mode, "w+")) {
207     mde = O_RDWR | O_CREAT | O_TRUNC;
208     } else if (0 == strcasecmp(mode, "a+")) {
209     mde = O_RDWR | O_CREAT | O_APPEND;
210     } else if (0 == strcasecmp(mode, "r")) {
211     mde = O_RDONLY;
212     } else if (0 == strcasecmp(mode, "w")) {
213     mde = O_WRONLY | O_CREAT | O_TRUNC;
214     } else if (0 == strcasecmp(mode, "a")) {
215     mde = O_WRONLY | O_APPEND | O_CREAT;
216     } else {
217     mde = O_RDONLY;
218     }
219     return (mde);
220     }
221    
222     /* Get current position in file */
223 azarah 43 SB_STATIC long file_tell(int fp)
224 ferringb 2 {
225     return (lseek(fp, 0L, SEEK_CUR));
226     }
227    
228     /* lock the file, preferrably the POSIX way */
229 azarah 43 SB_STATIC int file_lock(int fd, int lock, char *filename)
230 ferringb 2 {
231     int err;
232     #ifdef USE_FLOCK
233     if (flock(fd, lock) < 0) {
234     err = errno;
235     fprintf(stderr, ">>> %s flock file lock: %s\n", filename, strerror(err));
236     return 0;
237     }
238     #else
239     struct flock fl;
240     fl.l_type = lock;
241     fl.l_whence = SEEK_SET;
242     fl.l_start = 0L;
243     fl.l_len = 0L;
244     fl.l_pid = getpid();
245     if (fcntl(fd, F_SETLKW, &fl) < 0) {
246     err = errno;
247     fprintf(stderr, ">>> %s fcntl file lock: %s\n", filename, strerror(err));
248     return 0;
249     }
250     #endif
251     return 1;
252     }
253    
254     /* unlock the file, preferrably the POSIX way */
255 azarah 43 SB_STATIC int file_unlock(int fd)
256 ferringb 2 {
257     #ifdef USE_FLOCK
258     if (flock(fd, LOCK_UN) < 0) {
259     perror(">>> flock file unlock");
260     return 0;
261     }
262     #else
263     struct flock fl;
264     fl.l_type = F_UNLCK;
265     fl.l_whence = SEEK_SET;
266     fl.l_start = 0L;
267     fl.l_len = 0L;
268     fl.l_pid = getpid();
269     if (fcntl(fd, F_SETLKW, &fl) < 0) {
270     perror(">>> fcntl file unlock");
271     return 0;
272     }
273     #endif
274     return 1;
275     }
276    
277     /* Auto-determine from how the file was opened, what kind of lock to lock
278     * the file with
279     */
280 azarah 43 SB_STATIC int file_locktype(char *mode)
281 ferringb 2 {
282     #ifdef USE_FLOCK
283     if (NULL != (strchr(mode, 'w')) || (NULL != strchr(mode, '+'))
284 azarah 30 || (NULL != strchr(mode, 'a')))
285 ferringb 2 return (LOCK_EX);
286     return (LOCK_SH);
287     #else
288     if (NULL != (strchr(mode, 'w')) || (NULL != strchr(mode, '+'))
289 azarah 30 || (NULL != strchr(mode, 'a')))
290 ferringb 2 return (F_WRLCK);
291     return (F_RDLCK);
292     #endif
293     }
294    
295     /* Use standard fopen style modes to open the specified file. Also auto-determines and
296     * locks the file either in shared or exclusive mode depending on opening mode
297     */
298 azarah 43 SB_STATIC int file_open(char *filename, char *mode, int perm_specified, ...)
299 ferringb 2 {
300     int fd;
301 azarah 93 char error[SB_BUF_LEN];
302 ferringb 2 va_list ap;
303     int perm;
304     char *group = NULL;
305     struct group *group_struct;
306 azarah 30
307 ferringb 2 file_security_check(filename);
308    
309     if (perm_specified) {
310     va_start(ap, perm_specified);
311     perm = va_arg(ap, int);
312     group = va_arg(ap, char *);
313     va_end(ap);
314     }
315     fd = open(filename, file_getmode(mode));
316     file_security_check(filename);
317     if (-1 == fd) {
318     snprintf(error, sizeof(error), ">>> %s file mode: %s open", filename, mode);
319     perror(error);
320     return (fd);
321     }
322     if (perm_specified) {
323     if (fchmod(fd, 0664) && (0 == getuid())) {
324     snprintf(error, sizeof(error), ">>> Could not set mode: %s", filename);
325     perror(error);
326     }
327     }
328     if (NULL != group) {
329     group_struct = getgrnam(group);
330 azarah 82 if (NULL == group_struct) {
331 ferringb 2 snprintf(error, sizeof(error), ">>> Could not get grp number: %s", group);
332     perror(error);
333     } else {
334     if (fchown(fd, -1, group_struct->gr_gid) && (0 == getuid())) {
335     snprintf(error, sizeof(error), ">>> Could not set group: %s", filename);
336     perror(error);
337     }
338     }
339     }
340     /* Only lock the file if opening succeeded */
341     if (-1 != fd) {
342 azarah 30 if (file_security_check(filename) != 0) {
343     /* Security violation occured between the last check and the */
344 ferringb 2 /* creation of the file. As SpanKY pointed out there is a race */
345     /* condition here, so if there is a problem here we'll mesg and */
346     /* bail out to avoid it until we can work and test a better fix. */
347     fprintf(stderr, "\n\nSECURITY RACE CONDITION: Problem recurred after creation!\nBAILING OUT\n\n");
348     exit(127);
349     }
350    
351     if (0 == file_lock(fd, file_locktype(mode), filename)) {
352     close(fd);
353     return -1;
354     }
355     } else {
356     snprintf(error, sizeof(error), ">>> %s file mode:%s open", filename, mode);
357     perror(error);
358     }
359     return (fd);
360     }
361    
362     /* Close and unlock file */
363 azarah 43 SB_STATIC void file_close(int fd)
364 ferringb 2 {
365     if (-1 != fd) {
366     file_unlock(fd);
367     close(fd);
368     }
369     }
370    
371     /* Return length of file */
372 azarah 43 SB_STATIC long file_length(int fd)
373 ferringb 2 {
374     long pos, len;
375     pos = file_tell(fd);
376     len = lseek(fd, 0L, SEEK_END);
377     lseek(fd, pos, SEEK_SET);
378     return (len);
379     }
380    
381     /* Zero out file */
382 azarah 43 SB_STATIC int file_truncate(int fd)
383 ferringb 2 {
384     lseek(fd, 0L, SEEK_SET);
385     if (ftruncate(fd, 0) < 0) {
386     perror(">>> file truncate");
387     return 0;
388     }
389     return 1;
390     }
391    
392     /* Check to see if a file exists Return: 1 success, 0 file not found, -1 error */
393 azarah 43 SB_STATIC int file_exist(char *filename, int checkmode)
394 ferringb 2 {
395     struct stat mystat;
396    
397     /* Verify file exists and is regular file (not sym link) */
398     if (checkmode) {
399     if (-1 == lstat(filename, &mystat)) {
400     /* file doesn't exist */
401     if (ENOENT == errno) {
402     return 0;
403 azarah 30 } else { /* permission denied or other error */
404 ferringb 2 perror(">>> stat file");
405     return -1;
406     }
407     }
408     if (!S_ISREG(mystat.st_mode))
409     return -1;
410    
411     /* Just plain verify the file exists */
412     } else {
413     if (-1 == stat(filename, &mystat)) {
414     /* file does not exist */
415     if (ENOENT == errno) {
416     return 0;
417 azarah 30 } else { /* permission denied or other error */
418 ferringb 2 perror(">>> stat file");
419     return -1;
420     }
421     }
422     }
423    
424     return 1;
425     }
426    
427 azarah 43 SB_STATIC int file_security_check(char *filename)
428 azarah 30 { /* 0 == fine, >0 == problem */
429 ferringb 2 struct stat stat_buf;
430     struct group *group_buf;
431     struct passwd *passwd_buf;
432 azarah 30
433 ferringb 2 passwd_buf = getpwnam("portage");
434     group_buf = getgrnam("portage");
435    
436 azarah 30 if ((lstat(filename, &stat_buf) == -1) && (errno == ENOENT)) {
437 ferringb 2 /* Doesn't exist. */
438     return 0;
439 azarah 30 } else {
440     if ((stat_buf.st_nlink) > 1) { /* Security: We are handlinked... */
441     if (unlink(filename)) {
442     fprintf(stderr, "Unable to delete file in security violation (hardlinked): %s\n", filename);
443 ferringb 2 exit(127);
444     }
445 azarah 30 fprintf(stderr, "File in security violation (hardlinked): %s\n", filename);
446 ferringb 2 return 1;
447 azarah 30 } else if (S_ISLNK(stat_buf.st_mode)) { /* Security: We are a symlink? */
448     fprintf(stderr, "File in security violation (symlink): %s\n", filename);
449 ferringb 2 exit(127);
450 azarah 30 } else if (0 == S_ISREG(stat_buf.st_mode)) { /* Security: special file */
451     fprintf(stderr, "File in security violation (not regular): %s\n", filename);
452 ferringb 2 exit(127);
453 azarah 30 } else if (stat_buf.st_mode & S_IWOTH) { /* Security: We are o+w? */
454     if (unlink(filename)) {
455     fprintf(stderr, "Unable to delete file in security violation (world write): %s\n", filename);
456 ferringb 2 exit(127);
457     }
458 azarah 30 fprintf(stderr, "File in security violation (world write): %s\n", filename);
459 ferringb 2 return 1;
460 azarah 30 } else
461     if (!((stat_buf.st_uid == 0) || (stat_buf.st_uid == getuid()) ||
462     ((passwd_buf != NULL) && (stat_buf.st_uid == passwd_buf->pw_uid))) ||
463     !((stat_buf.st_gid == 0) || (stat_buf.st_gid == getgid()) ||
464     ((group_buf != NULL) && (stat_buf.st_gid == group_buf->gr_gid)))) {
465     /* Security: Owner/Group isn't right. */
466    
467 ferringb 2 /* uid = 0 or myuid or portage */
468     /* gid = 0 or mygid or portage */
469 azarah 30
470     if (0) {
471 ferringb 2 fprintf(stderr, "--1: %d,%d,%d,%d\n--2: %d,%d,%d,%d\n",
472     (stat_buf.st_uid == 0),
473     (stat_buf.st_uid == getuid()),
474 azarah 30 (passwd_buf != NULL),
475     (passwd_buf != NULL) ? (stat_buf.st_uid == passwd_buf->pw_uid) : -1,
476     (stat_buf.st_gid == 0),
477 ferringb 2 (stat_buf.st_gid == getgid()),
478 azarah 30 (group_buf != NULL),
479     (group_buf != NULL) ? (stat_buf.st_gid == group_buf->gr_gid) : -1);
480 ferringb 2 }
481 azarah 30
482 ferringb 2 /* manpage: "The return value may point to static area" */
483     /* DO NOT ACTUALLY FREE THIS... It'll segfault. */
484     /* if(passwd_buf != NULL) { free(passwd_buf); } */
485     /* if(group_buf != NULL) { free(group_buf); } */
486 azarah 30
487     if (unlink(filename)) {
488     fprintf(stderr, "Unable to delete file in security violation (bad owner/group): %s\n", filename);
489 ferringb 2 exit(127);
490     }
491 azarah 30 fprintf(stderr, "File in security violation (bad owner/group): %s\n", filename);
492 ferringb 2 return 1;
493     }
494 azarah 30 } /* Stat */
495 ferringb 2 return 0;
496     }
497    
498 azarah 30 // vim:noexpandtab noai:cindent ai

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.20