commit permissions for openSUSE:Factory
Hello community, here is the log from the commit of package permissions for openSUSE:Factory checked in at Wed Nov 10 20:26:53 CET 2010. -------- --- permissions/permissions.changes 2010-10-18 15:38:41.000000000 +0200 +++ permissions/permissions.changes 2010-11-09 13:51:35.000000000 +0100 @@ -1,0 +2,30 @@ +Tue Nov 9 12:51:10 UTC 2010 - lnussel@suse.de + +- add permissions man page +- update docu +- add --level option +- set perms for setuid files always if owner changes +- strip root dir when printing file names + +------------------------------------------------------------------- +Tue Nov 9 09:25:17 UTC 2010 - lnussel@suse.de + +- add option to explicitly warn only + +------------------------------------------------------------------- +Fri Nov 5 14:00:30 UTC 2010 - lnussel@suse.de + +- reimplement the core features in chkstat itself instead of + SuSEconfig.permissions + +------------------------------------------------------------------- +Thu Nov 4 16:17:25 UTC 2010 - lnussel@suse.de + +- don't make changes if not called explicitly + +------------------------------------------------------------------- +Wed Nov 3 14:16:54 UTC 2010 - lnussel@suse.de + +- add support for file system capabilities + +------------------------------------------------------------------- calling whatdependson for head-i586 Old: ---- permissions-2010.10.18.1537.tar.bz2 New: ---- permissions-2010.11.09.1206.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ permissions.spec ++++++ --- /var/tmp/diff_new_pack.QcgxAn/_old 2010-11-10 20:21:57.000000000 +0100 +++ /var/tmp/diff_new_pack.QcgxAn/_new 2010-11-10 20:21:57.000000000 +0100 @@ -1,5 +1,5 @@ # -# spec file for package permissions (Version 2010.10.18.1537) +# spec file for package permissions (Version 2010.11.09.1206) # # Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany. # @@ -18,12 +18,13 @@ # norootforbuild # icecream 0 +BuildRequires: libcap-devel Name: permissions License: GPLv2+ Group: Productivity/Security AutoReqProv: on -Version: 2010.10.18.1537 +Version: 2010.11.09.1206 Release: 1 Provides: aaa_base:/etc/permissions Requires: /sbin/SuSEconfig @@ -68,6 +69,7 @@ %config /etc/permissions.paranoid %config(noreplace) /etc/permissions.local %{_bindir}/chkstat +%{_mandir}/man5/permissions.5* %{_mandir}/man8/chkstat.8* /sbin/conf.d/SuSEconfig.permissions /var/adm/fillup-templates/sysconfig.security ++++++ permissions-2010.10.18.1537.tar.bz2 -> permissions-2010.11.09.1206.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/permissions-2010.10.18.1537/Makefile new/permissions-2010.11.09.1206/Makefile --- old/permissions-2010.10.18.1537/Makefile 2010-10-18 15:37:12.000000000 +0200 +++ new/permissions-2010.11.09.1206/Makefile 2010-11-09 12:06:11.000000000 +0100 @@ -1,6 +1,7 @@ CFLAGS=-W -Wall -g -O2 CC=gcc DESTDIR= +LDLIBS=-lcap prefix=/usr sysconfdir=/etc bindir=$(prefix)/bin @@ -9,15 +10,17 @@ datadir=$(prefix)/share mandir=$(datadir)/man man8dir=$(mandir)/man8 +man5dir=$(mandir)/man5 all: chkstat install: all - @for i in $(bindir) $(suseconfigdir) $(man8dir) $(fillupdir) $(sysconfdir); \ + @for i in $(bindir) $(suseconfigdir) $(man8dir) $(man5dir) $(fillupdir) $(sysconfdir); \ do install -d -m 755 $(DESTDIR)$$i; done @install -m 755 chkstat $(DESTDIR)$(bindir) @install -m 755 SuSEconfig.permissions $(DESTDIR)$(suseconfigdir) @install -m 644 chkstat.8 $(DESTDIR)$(man8dir) + @install -m 644 permissions.5 $(DESTDIR)$(man5dir) @install -m 644 sysconfig.security $(DESTDIR)$(fillupdir) @for i in permissions{,.local,.easy,.secure,.paranoid}; \ do install -m 644 $$i $(DESTDIR)$(sysconfdir); done diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/permissions-2010.10.18.1537/SuSEconfig.permissions new/permissions-2010.11.09.1206/SuSEconfig.permissions --- old/permissions-2010.10.18.1537/SuSEconfig.permissions 2010-10-18 15:37:12.000000000 +0200 +++ new/permissions-2010.11.09.1206/SuSEconfig.permissions 2010-11-09 12:06:11.000000000 +0100 @@ -24,63 +24,9 @@ . /lib/YaST/SuSEconfig.functions || exit 1 -for i in /etc/sysconfig/security /etc/sysconfig/suseconfig ; do - . $i || exit 1 -done - if test -n "$ENABLE_SUSECONFIG" -a "$ENABLE_SUSECONFIG" = "no" ; then echo "SuSEconfig is disabled in /etc/sysconfig/suseconfig" exit 0 fi -mode="" -case "$CHECK_PERMISSIONS" in - set) mode="-set" ;; - warn) ;; - no|"") exit 0 ;; - *) echo "invalid value '$CHECK_PERMISSIONS' for \$CHECK_PERMISSIONS" >&2 ;; -esac - - - -# collect files that contain permission specifications -# -# 1. central fixed permissions file -files="/etc/permissions" - -# 2. central easy, secure paranoid as those are defined by SUSE -for level in $PERMISSION_SECURITY; do - case "$level" in - easy|secure|paranoid) - if [ -e /etc/permissions.$level ]; then - files="$files /etc/permissions.$level" - fi - ;; - esac -done - -# 3. package specific permissions -pkgfiles=(/etc/permissions.d/*) -pkgfiles=(${pkgfiles[*]##*/}) -pkgfiles=(${pkgfiles[*]%%.*}) -pkgfiles=(`for i in ${pkgfiles[@]}; do echo $i; done | /usr/bin/sort -u`) - -for file in ${pkgfiles[@]}; do - file=/etc/permissions.d/$file - [ -e $file ] && files="$files $file" - for level in $PERMISSION_SECURITY; do - [ -e $file.$level ] && files="$files $file.$level" - done -done - -# 4. central permissions files with user defined level incl 'local' -for level in $PERMISSION_SECURITY; do - case "$level" in - easy|secure|paranoid) continue ;; - esac - if [ -e /etc/permissions.$level ]; then - files="$files /etc/permissions.$level" - fi -done - -/usr/bin/chkstat $mode $files +/usr/bin/chkstat --suseconfig $mode diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/permissions-2010.10.18.1537/checkpermissionfiles.pl new/permissions-2010.11.09.1206/checkpermissionfiles.pl --- old/permissions-2010.10.18.1537/checkpermissionfiles.pl 2010-10-18 15:37:12.000000000 +0200 +++ new/permissions-2010.11.09.1206/checkpermissionfiles.pl 2010-11-09 12:06:11.000000000 +0100 @@ -87,8 +87,11 @@ { chomp; s/#.*//; + s/^\s.*//; next if(/^$/); + next if(/^\+/); # XXX ext line + my ($file, $owner, $mode) = split(/\s+/); if(!$nodups && exists($perms{$file}{$level})) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/permissions-2010.10.18.1537/chkstat.8 new/permissions-2010.11.09.1206/chkstat.8 --- old/permissions-2010.10.18.1537/chkstat.8 2010-10-18 15:37:12.000000000 +0200 +++ new/permissions-2010.11.09.1206/chkstat.8 2010-11-09 12:06:11.000000000 +0100 @@ -3,7 +3,7 @@ .\" .\" Author: Ruediger Oertel .\" -.TH CHKSTAT 8 "2008-04-17" "SUSE Linux" "Tool to check and set file permissions" +.TH CHKSTAT 8 "2010-11-09" "SUSE Linux" "Tool to check and set file permissions" .\" .UC 8 .SH NAME @@ -12,67 +12,81 @@ .SH SYNOPSIS .\" .B chkstat -.RB \|[\| \-\-set|\-set ] -.RB \|[\| \-\-noheader ] -.RB \|[\|\|[\| \-\-examine\ file\ ] ... ] -.RB \|[\|\|[\| \-\-files\ filelist\ ] ... ] -.RB \|[\|\|[\| \-\-root\ directory\ ] ... ] -.B permission-file ... +.RB [OPTIONS] +.B <permission-files...> + +.B chkstat +.RB \-\-system +.RB [OPTIONS] +.B <files...> .\" .SH DESCRIPTION The program .I /usr/bin/chkstat is a tool to check and set file permissions. .PP -Multiple permissions files can be given on the commandline. -If the permission files contain multiple entries for a single -file, the last entry found will be used. +chkstat can either operate in system mode or on individually +specified permission files. In system mode /etc/permissions/security +determines which level to use and whether to actually apply +permission changes. .PP .\" -.SS General Options +.SS OPTIONS +.TP +.IR \-\-system +Run in system mode. Parses \fI/etc/sysconfig/security\fR to +determine which security level to use (\fIPERMISSION_SECURITY\fR) +and whether to set or merely warn about permission changes +(\fICHECK_PERMISSIONS\fR). In system mode non-option arguments refer +to files. Ie just as if the \-\-examine option was specified for them. .TP -.IR \-\-set ,\ \-set -This option enables setting the file permissions, -the default is to check and warn only. +.IR \-\-set +Actually apply the file permissions. The default is to check and +warn only unless in system mode where \fICHECK_PERMISSIONS\fR +specifies the default behavior. +.TP +.IR \-\-warn +Opposite of --set, ie warn only but don't make actual changes .TP .IR \-\-noheader Omit printing the output header lines. .TP +.IR \-\-fscaps,\ \-\-no\-fscaps +Force or disable use of fscaps. Default is to automatically +determine whether the running kernel supports fscaps. +.TP .IR \-\-examine\ file -Check permissions for this file and not all files listed in the permissions files. +Check permissions for this file instead of all files listed in the permissions files. .TP .IR \-\-files\ filelist Check permissions for the files listed in .IR filelist -and not for all files listed in the permissions files. +and instead of all files listed in the permissions files. .TP .IR \-\-root\ directory -Prefix the files given in the permissions files by this directory. -.PP -.SH EXAMPLE +Check files relative to the specified directory. .PP -The command +.SH EXAMPLES .PP -.RS -.B chkstat -set /etc/permissions -.RE +.B chkstat --set /etc/permissions /etc/permissions.secure .PP -will parse the file /etc/permissions and set the access mode and the -user- and group memberships each file listed. The format -for the input file is +parses the files /etc/permissions and /etc/permissions and sets the +access mode and the user- and group memberships for each file listed. .PP -.B FILEPATH -.B OWNER:GROUP -.B MODE +.B chkstat --system /bin/ping .PP -and wildcards are not supported for the filepath. Lines starting -with '#' and empty lines are treated as comments. +Run in system mode and only correct permissions of /bin/ping +. +.SH "SEE ALSO" +.sp +permissions(5) +. .SH COPYRIGHT 1996-2003 SuSE Linux AG, Nuernberg, Germany. -2008 SUSE LINUX Products GmbH +2008-2010 SUSE LINUX Products GmbH .SH AUTHORS -Reinhold Sojer, Ruediger Oertel, Michael Schroeder +Reinhold Sojer, Ruediger Oertel, Michael Schroeder, Ludwig Nussel .PP Useful changes and additions by Tobias Burnus diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/permissions-2010.10.18.1537/chkstat.c new/permissions-2010.11.09.1206/chkstat.c --- old/permissions-2010.10.18.1537/chkstat.c 2010-10-18 15:37:12.000000000 +0200 +++ new/permissions-2010.11.09.1206/chkstat.c 2010-11-09 12:06:11.000000000 +0100 @@ -27,9 +27,13 @@ #include <stdlib.h> #include <string.h> #include <errno.h> +#include <dirent.h> +#include <sys/capability.h> #define __USE_GNU #include <fcntl.h> +#define BAD_LINE() \ + fprintf(stderr, "bad permissions line %s:%d\n", argv[i], lcnt); struct perm { struct perm *next; @@ -37,6 +41,7 @@ char *owner; char *group; mode_t mode; + cap_t caps; }; struct perm *permlist; @@ -45,8 +50,15 @@ uid_t euid; char *root; int rootl; +int nlevel; +char** level; +int do_set = -1; +int default_set = 0; +char** permfiles = NULL; +int npermfiles = 0; +char* force_level; -void +struct perm* add_permlist(char *file, char *owner, char *group, mode_t mode) { struct perm *ec, **epp; @@ -94,8 +106,10 @@ ec->owner = owner; ec->group = group; ec->mode = mode; + ec->caps = NULL; ec->next = 0; *epp = ec; + return ec; } int @@ -155,10 +169,244 @@ return 1; } +int +in_level(char *e) +{ + int i; + for (i = 0; i < nlevel; i++) + if (!strcmp(e, level[i])) + return 1; + return 0; +} + +void +ensure_array(void** array, int* size) +{ + if ((*size & 63) == 0) + { + if (*array == NULL) + *array = malloc(sizeof(char *) * (*size + 64)); + else + *array = realloc(*array, sizeof(char *) * (*size + 64)); + if (*array == NULL) + { + perror("array alloc"); + exit(1); + } + } +} + +void +add_level(char *e) +{ + if (in_level(e)) + return; + e = strdup(e); + if (e == 0) + { + perror("level entry alloc"); + exit(1); + } + ensure_array((void**)&level, &nlevel); + level[nlevel++] = e; +} + +static inline int isquote(char c) +{ + return (c == '"' || c == '\''); +} + +int +parse_sysconf(const char* file) +{ + FILE* fp; + char line[1024]; + char* p; + if ((fp = fopen(file, "r")) == 0) + { + fprintf(stderr, "error opening: %s: %s\n", file, strerror(errno)); + return 0; + } + while (readline(fp, line, sizeof(line))) + { + if (!*line) + continue; + for (p = line; *p == ' '; ++p); + if (!*p || *p == '#') + continue; + if (!strncmp(p, "PERMISSION_SECURITY=", 20)) + { + if (force_level) + continue; + + p+=20; + if (isquote(*p)) + ++p; + p = strtok(p, " "); + if (p && !isquote(*p)) + { + do + { + if (isquote(p[strlen(p)-1])) + { + p[strlen(p)-1] = '\0'; + } + if (*p && strcmp(p, "local")) + add_level(p); + } + while ((p = strtok(NULL, " "))); + } + } + else if (!strncmp(p, "CHECK_PERMISSIONS=", 18)) + { + p+=18; + if (isquote(*p)) + ++p; + if (!strncmp(p, "set", 3)) + { + p+=3; + if (isquote(*p) || !*p) + default_set=1; + } + else if ((!strncmp(p, "no", 2) && (!p[3] || isquote(p[3]))) || !*p || isquote(*p)) + { + p+=2; + if (isquote(*p) || !*p) + { + default_set = -1; + } + } + else + { + //fprintf(stderr, "invalid value for CHECK_PERMISSIONS (must be 'set', 'warn' or 'no')\n"); + } + } + } + fclose(fp); + return 0; +} + +static int +compare(const void* a, const void* b) +{ + return strcmp(*(char* const*)a, *(char* const*)b); +} + +static void +collect_permfiles() +{ + int i; + DIR* dir; + + ensure_array((void**)&permfiles, &npermfiles); + // 1. central fixed permissions file + permfiles[npermfiles++] = strdup("/etc/permissions"); + + // 2. central easy, secure paranoid as those are defined by SUSE + for (i = 0; i < nlevel; ++i) + { + if (!strcmp(level[i], "easy") + || !strcmp(level[i], "secure") + || !strcmp(level[i], "paranoid")) + { + char fn[4096]; + snprintf(fn, sizeof(fn), "/etc/permissions.%s", level[i]); + if (access(fn, R_OK) == 0) + { + ensure_array((void**)&permfiles, &npermfiles); + permfiles[npermfiles++] = strdup(fn); + } + } + } + // 3. package specific permissions + dir = opendir("/etc/permissions.d"); + if (dir) + { + char** files = NULL; + int nfiles = 0; + struct dirent* d; + while ((d = readdir(dir))) + { + char* p; + if (!strcmp("..", d->d_name) || !strcmp(".", d->d_name)) + continue; + ensure_array((void**)&files, &nfiles); + if ((p = strchr(d->d_name, '.'))) + { + *p = '\0'; + } + files[nfiles++] = strdup(d->d_name); + } + closedir(dir); + if (nfiles) + { + qsort(files, nfiles, sizeof(char*), compare); + for (i = 0; i < nfiles; ++i) + { + char fn[4096]; + int l; + // skip duplicates + if (i && !strcmp(files[i-1], files[i])) + continue; + + snprintf(fn, sizeof(fn), "/etc/permissions.d/%s", files[i]); + if (access(fn, R_OK) == 0) + { + ensure_array((void**)&permfiles, &npermfiles); + permfiles[npermfiles++] = strdup(fn); + } + + for (l = 0; l < nlevel; ++l) + { + snprintf(fn, sizeof(fn), "/etc/permissions.d/%s.%s", files[i], level[l]); + + if (access(fn, R_OK) == 0) + { + ensure_array((void**)&permfiles, &npermfiles); + permfiles[npermfiles++] = strdup(fn); + } + } + + } + } + } + // 4. central permissions files with user defined level incl 'local' + for (i = 0; i < nlevel; ++i) + { + char fn[4096]; + + if (!strcmp(level[i], "easy") || !strcmp(level[i], "secure") || !strcmp(level[i], "paranoid")) + continue; + + snprintf(fn, sizeof(fn), "/etc/permissions.%s", level[i]); + if (access(fn, R_OK) == 0) + { + ensure_array((void**)&permfiles, &npermfiles); + permfiles[npermfiles++] = strdup(fn); + } + } +} + + void usage(int x) { - fprintf(stderr, "Usage: chkstat [--set] [--noheader] [[--examine file] ...] [ [--files filelist] ...] permission-file ...\n"); + printf("Usage:\n" +"a) chkstat [OPTIONS] <permission-files>...\n" +"b) chkstat --system [OPTIONS] <files>...\n" +"\n" +"Options:\n" +" --set apply changes\n" +" --warn only tell which changes are needed\n" +" --noheader don't print intro message\n" +" --fscaps force use of fscaps\n" +" --no-fscaps disable use of fscaps\n" +" --system system mode, act according to /etc/permissions/security\n" +" --level LEVEL force use LEVEL (only with --system)\n" +" --examine FILE apply to specified file only\n" +" --files FILELIST read list of files to apply from FILELIST\n" +" --root DIR check files relative to DIR\n" +); exit(x); } @@ -173,7 +421,7 @@ lcnt = 0; l2 = strlen(path); - if (l2 >= sizeof(pathbuf)) + if ((unsigned)l2 >= sizeof(pathbuf)) return 0; strcpy(pathbuf, path); if (pathbuf[0] != '/') @@ -192,11 +440,11 @@ if (++lcnt >= 256) return 0; l = readlink(pathbuf, linkbuf, sizeof(linkbuf)); - if (l <= 0 || l >= sizeof(linkbuf)) + if (l <= 0 || (unsigned)l >= sizeof(linkbuf)) return 0; while(l && linkbuf[l - 1] == '/') l--; - if (l + 1 >= sizeof(linkbuf)) + if ((unsigned)l + 1 >= sizeof(linkbuf)) return 0; linkbuf[l++] = '/'; linkbuf[l] = 0; @@ -228,7 +476,7 @@ l2 -= (p - p2); p = p2; } - if (l + l2 >= sizeof(pathbuf)) + if ((unsigned)(l + l2) >= sizeof(pathbuf)) return 0; memmove(p + l, p, pathbuf + l2 - p + 1); memmove(p, linkbuf, l); @@ -261,13 +509,39 @@ } } +/* that's really ugly. There should be sysctl or something */ +static int +check_fscaps_cmdline() +{ + FILE* fp; + char line[4096]; + if ((fp = fopen("/proc/cmdline", "r")) == 0) + { + return 0; + } + if (readline(fp, line, sizeof(line))) + { + char* p; + if ((p = strstr(line, "file_caps"))) + { + if (p - line < 3 || strncmp("no_", p, 3)) + { + return 1; + } + } + } + fclose(fp); + return 0; +} + int main(int argc, char **argv) { - char *opt, *p; - int set = 0; + char *opt, *p, *str; int told = 0; int use_checklist = 0; + int systemmode = 0; + int suseconfig = 0; FILE *fp; char line[512]; char *part[4]; @@ -282,6 +556,8 @@ gid_t gid; int fd, r; int errors = 0; + cap_t caps = NULL; + int have_fscaps = -1; while (argc > 1) { @@ -290,9 +566,46 @@ break; if (*opt == '-' && opt[1] == '-') opt++; + if (!strcmp(opt, "-system")) + { + argc--; + argv++; + systemmode = 1; + continue; + } + // hidden option for use by suseconfig only + if (!strcmp(opt, "-suseconfig")) + { + argc--; + argv++; + suseconfig = 1; + systemmode = 1; + continue; + } + if (!strcmp(opt, "-fscaps")) + { + argc--; + argv++; + have_fscaps = 1; + continue; + } + if (!strcmp(opt, "-no-fscaps")) + { + argc--; + argv++; + have_fscaps = 0; + continue; + } if (!strcmp(opt, "-s") || !strcmp(opt, "-set")) { - set = 1; + do_set=1; + argc--; + argv++; + continue; + } + if (!strcmp(opt, "-warn")) + { + do_set=0; argc--; argv++; continue; @@ -319,6 +632,20 @@ argv++; continue; } + if (!strcmp(opt, "-level")) + { + argc--; + argv++; + if (argc == 1) + { + fprintf(stderr, "level: argument required\n"); + exit(1); + } + force_level = argv[1]; + argc--; + argv++; + continue; + } if (!strcmp(opt, "-f") || !strcmp(opt, "-files")) { argc--; @@ -369,18 +696,78 @@ usage(!strcmp(opt, "-h") || !strcmp(opt, "-help") ? 0 : 1); break; } - if (argc <= 1) + + if (have_fscaps == -1) + have_fscaps = check_fscaps_cmdline(); + + if (systemmode) + { + const char file[] = "/etc/sysconfig/security"; + parse_sysconf(file); + if(do_set == -1) + { + if (default_set < 0) + { + fprintf(stderr, "permissions handling disabled in %s\n", file); + exit(0); + } + if (suseconfig && default_set) + { + char* module = getenv("ONLY_MODULE"); + if (!module || strcmp(module, "permissions")) + { + puts("no permissions will be changed if not called explicitly"); + default_set = 0; + } + } + do_set = default_set; + } + if (force_level) + { + char *p = strtok(force_level, " "); + do + { + add_level(p); + } + while ((p = strtok(NULL, " "))); + } + + if (!nlevel) + add_level("secure"); + add_level("local"); // always add local + + for (i = 1; i < argc; i++) + { + add_checklist(argv[i]); + use_checklist = 1; + continue; + } + collect_permfiles(); + } + else if (argc <= 1) usage(1); - for (i = 1; i < argc; i++) + else { - if ((fp = fopen(argv[i], "r")) == 0) + npermfiles = argc-1; + permfiles = &argv[1]; + } + + if (do_set == -1) + do_set = 0; + + for (i = 0; i < npermfiles; i++) + { + if ((fp = fopen(permfiles[i], "r")) == 0) { perror(argv[i]); exit(1); } lcnt = 0; + struct perm* last = NULL; + int extline; while (readline(fp, line, sizeof(line))) { + extline = 0; lcnt++; if (*line == 0 || *line == '#' || *line == '$') continue; @@ -398,6 +785,11 @@ } continue; } + if (pcnt == 0 && !inpart && *p == '+') + { + extline = 1; + break; + } if (!inpart) { inpart = 1; @@ -406,11 +798,34 @@ part[pcnt] = p; } } + if (extline) + { + if (!last) + { + BAD_LINE(); + continue; + } + if (!strncmp(p, "+capabilities ", 14)) + { + if (!have_fscaps) + continue; + p += 14; + caps = cap_from_text(p); + if (caps) + { + cap_free(last->caps); + last->caps = caps; + } + continue; + } + BAD_LINE(); + continue; + } if (inpart) pcnt++; if (pcnt != 3) { - fprintf(stderr, "bad permissions line %s:%d\n", argv[i], lcnt); + BAD_LINE(); continue; } part[3] = part[2]; @@ -419,17 +834,17 @@ part[2] = strchr(part[1], '.'); if (!part[2]) { - fprintf(stderr, "bad permissions line %s:%d\n", argv[i], lcnt); + BAD_LINE(); continue; } *part[2]++ = 0; mode = strtoul(part[3], part + 3, 8); if (mode > 07777 || part[3][0]) { - fprintf(stderr, "bad permissions line %s:%d\n", argv[i], lcnt); + BAD_LINE(); continue; } - add_permlist(part[0], part[1], part[2], mode); + last = add_permlist(part[0], part[1], part[2], mode); } fclose(fp); } @@ -445,33 +860,74 @@ continue; if ((!pwd || strcmp(pwd->pw_name, e->owner)) && (pwd = getpwnam(e->owner)) == 0) { - fprintf(stderr, "%s: unknown user %s\n", e->file, e->owner); + fprintf(stderr, "%s: unknown user %s\n", e->file+rootl, e->owner); continue; } if ((!grp || strcmp(grp->gr_name, e->group)) && (grp = getgrnam(e->group)) == 0) { - fprintf(stderr, "%s: unknown group %s\n", e->file, e->group); + fprintf(stderr, "%s: unknown group %s\n", e->file+rootl, e->group); continue; } uid = pwd->pw_uid; gid = grp->gr_gid; - if ((stb.st_mode & 07777) == e->mode && stb.st_uid == uid && stb.st_gid == gid) + caps = cap_get_file(e->file); + if (!caps) + { + cap_free(caps); + caps = NULL; + if (errno == EOPNOTSUPP) + { + //fprintf(stderr, "%s: fscaps not supported\n", e->file+rootl); + cap_free(e->caps); + e->caps = NULL; + } + } + if (e->caps) + { + e->mode &= 0777; + } + + int perm_ok = (stb.st_mode & 07777) == e->mode; + int owner_ok = stb.st_uid == uid && stb.st_gid == gid; + int caps_ok = 0; + + if (!caps && !e->caps) + caps_ok = 1; + else if (caps && e->caps && !cap_compare(e->caps, caps)) + caps_ok = 1; + + if (perm_ok && owner_ok && caps_ok) continue; if (!told) { told = 1; printf("Checking permissions and ownerships - using the permissions files\n"); - for (i = 1; i < argc; i++) - printf("\t%s\n", argv[i]); + for (i = 0; i < npermfiles; i++) + printf("\t%s\n", permfiles[i]); + if (!have_fscaps) + { + printf("fscaps support disabled (file_caps missing in /proc/cmdline).\n"); + } + if (rootl) + { + printf("Using root %s\n", root); + } } - if (!set) - printf("%s should be %s:%s %04o.", e->file, e->owner, e->group, e->mode); + if (!do_set) + printf("%s should be %s:%s %04o", e->file+rootl, e->owner, e->group, e->mode); else - printf("setting %s to %s:%s %04o.", e->file, e->owner, e->group, e->mode); - printf(" (wrong"); - if (stb.st_uid != uid || stb.st_gid != gid) + printf("setting %s to %s:%s %04o", e->file+rootl, e->owner, e->group, e->mode); + + if (!caps_ok && e->caps) + { + str = cap_to_text(e->caps, NULL); + printf(" \"%s\"", str); + cap_free(str); + } + printf(". (wrong"); + if (!owner_ok) { pwd = getpwuid(stb.st_uid); grp = getgrgid(stb.st_gid); @@ -486,12 +942,29 @@ pwd = 0; grp = 0; } - if ((stb.st_mode & 07777) != e->mode) + + if (!perm_ok) printf(" permissions %04o", (int)(stb.st_mode & 07777)); + + if (!caps_ok) + { + if (!perm_ok || !owner_ok) + { + fputc(',', stdout); + } + if (caps) + { + str = cap_to_text(caps, NULL); + printf(" capabilities \"%s\"", str); + cap_free(str); + } + else + fputs(" missing capabilities", stdout); + } putchar(')'); putchar('\n'); - if (!set) + if (!do_set) continue; fd = -1; @@ -518,13 +991,13 @@ continue; if (stb.st_mode != stb2.st_mode || stb.st_nlink != stb2.st_nlink || stb.st_dev != stb2.st_dev || stb.st_ino != stb2.st_ino) { - fprintf(stderr, "%s: too fluctuating\n", e->file); + fprintf(stderr, "%s: too fluctuating\n", e->file+rootl); errors++; continue; } if (stb.st_nlink > 1 && !safepath(e->file, 0, 0)) { - fprintf(stderr, "%s: on an insecure path\n", e->file); + fprintf(stderr, "%s: on an insecure path\n", e->file+rootl); errors++; continue; } @@ -533,27 +1006,31 @@ /* extra checks for s-bits */ if (!safepath(e->file, (e->mode & 02000) == 0 ? uid : 0, (e->mode & 04000) == 0 ? gid : 0)) { - fprintf(stderr, "%s: will not give away s-bits on an insecure path\n", e->file); + fprintf(stderr, "%s: will not give away s-bits on an insecure path\n", e->file+rootl); errors++; continue; } } } - else if (strncmp(e->file, "/dev/", 4) != 0) + else if (strncmp(e->file, "/dev/", 5) != 0) // handle special files only in /dev { - fprintf(stderr, "%s: don't know what to do with that type of file\n", e->file); + fprintf(stderr, "%s: don't know what to do with that type of file\n", e->file+rootl); errors++; continue; } - if (euid == 0 && (stb.st_uid != uid || stb.st_gid != gid)) + if (euid == 0 && !owner_ok) { + /* if we change owner or group of a setuid file the bit gets reset so + also set perms again */ + if (e->mode & 06000) + perm_ok = 0; if (fd >= 0) r = fchown(fd, uid, gid); else r = chown(e->file, uid, gid); if (r) { - fprintf(stderr, "%s: chown: %s\n", e->file, strerror(errno)); + fprintf(stderr, "%s: chown: %s\n", e->file+rootl, strerror(errno)); errors++; } if (fd >= 0) @@ -562,12 +1039,12 @@ r = lstat(e->file, &stb); if (r) { - fprintf(stderr, "%s: too fluctuating\n", e->file); + fprintf(stderr, "%s: too fluctuating\n", e->file+rootl); errors++; continue; } } - if ((stb.st_mode & 07777) != e->mode) + if (!perm_ok) { if (fd >= 0) r = fchmod(fd, e->mode); @@ -575,7 +1052,19 @@ r = chmod(e->file, e->mode); if (r) { - fprintf(stderr, "%s: chmod: %s\n", e->file, strerror(errno)); + fprintf(stderr, "%s: chmod: %s\n", e->file+rootl, strerror(errno)); + errors++; + } + } + if (!caps_ok) + { + if (fd >= 0) + r = cap_set_fd(fd, e->caps); + else + r = cap_set_file(e->file, e->caps); + if (r) + { + fprintf(stderr, "%s: cap_set_file: %s\n", e->file+rootl, strerror(errno)); errors++; } } @@ -589,3 +1078,5 @@ } exit(0); } + +// vim: sw=4 cino+={.5s,n-.5s,^-.5s diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/permissions-2010.10.18.1537/permissions.5 new/permissions-2010.11.09.1206/permissions.5 --- old/permissions-2010.10.18.1537/permissions.5 1970-01-01 01:00:00.000000000 +0100 +++ new/permissions-2010.11.09.1206/permissions.5 2010-11-09 12:06:11.000000000 +0100 @@ -0,0 +1,48 @@ +.TH "PERMISSIONS" "5" "07/11/2010" "" "" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +permission - default permission settings +.SH "SYNOPSIS" +The chkstat program sets permissions and ownerships according to the +permission files\. +.SH "DESCRIPTION" +\- The files /etc/permissions\.* are line based and space delimited\. +.br +\- Lines starting with # are comments\. +.br +\- The first column specifies the file name\. Directory names have to +end with a slash\. +.br +\- The second column specifies the owner and group\. +.br +\- The third column specifies the file mode\. +.br +\- The special value \fB+capabilities\fR in the first column extends +the information of the previous line with with file capabilites. +.br +.SH "FILES" +.sp +/etc/permissions +.br +/etc/permissions\.easy +.br +/etc/permissions\.secure +.br +/etc/permissions\.paranoid +.br +/etc/permissions\.d/* +.br +/etc/permissions\.local +.br +.SH "SEE ALSO" +chkstat(8) +.sp +.SH "AUTHOR" +Written by Ludwig Nussel +.sp +.SH "REPORTING BUGS" +Report bugs to https://bugzilla\.novell\.com/ +.sp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/permissions-2010.10.18.1537/permissions.easy new/permissions-2010.11.09.1206/permissions.easy --- old/permissions-2010.10.18.1537/permissions.easy 2010-10-18 15:37:12.000000000 +0200 +++ new/permissions-2010.11.09.1206/permissions.easy 2010-11-09 12:06:11.000000000 +0100 @@ -197,7 +197,9 @@ # networking (need root for the privileged socket) # /bin/ping root:root 4755 + +capabilities cap_net_raw=ep /bin/ping6 root:root 4755 + +capabilities cap_net_raw=ep # mtr is linked against ncurses. For dialout only. /usr/sbin/mtr root:dialout 4750 /usr/bin/rcp root:root 4755 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/permissions-2010.10.18.1537/permissions.secure new/permissions-2010.11.09.1206/permissions.secure --- old/permissions-2010.10.18.1537/permissions.secure 2010-10-18 15:37:12.000000000 +0200 +++ new/permissions-2010.11.09.1206/permissions.secure 2010-11-09 12:06:11.000000000 +0100 @@ -235,7 +235,9 @@ # networking (need root for the privileged socket) # /bin/ping root:root 4755 + +capabilities cap_net_raw=ep /bin/ping6 root:root 4755 + +capabilities cap_net_raw=ep # mtr is linked against ncurses. no suid bit, for root only: /usr/sbin/mtr root:dialout 0755 /usr/bin/rcp root:root 4755 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... -- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org
participants (1)
-
root@hilbert.suse.de