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

Contents of /trunk/sandbox_futils.c

Parent Directory Parent Directory | Revision Log Revision Log


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