--- statcmd.c.before 2010-04-15 04:38:58.000000000 -0700 +++ statcmd.c 2010-06-14 02:09:51.470602032 -0700 @@ -47,7 +47,7 @@ #include "main.h" #include "filesdb.h" -const char thisname[] = "dpkg-statoverrides"; +const char thisname[] = "dpkg-statoverride"; const char printforhelp[] = N_( "Use --help for help about querying packages;\n" "Use --license for copyright license and lack of warranty (GNU GPL)."); --- statdb.c.before 2010-06-14 01:38:10.391099012 -0700 +++ statdb.c 2010-06-14 03:42:16.650606665 -0700 @@ -53,15 +53,17 @@ statdb_parse_uid(const char *str) long int value; value = strtol(str + 1, &endptr, 10); - if (str + 1 == endptr || *endptr || value < 0) + if (str + 1 == endptr || *endptr || value < -1) ohshit(_("syntax error: invalid uid in statoverride file")); uid = (uid_t)value; } else { struct passwd* pw = getpwnam(str); - if (pw == NULL) - ohshit(_("syntax error: unknown user '%s' in statoverride file"), - str); - uid = pw->pw_uid; + + if (pw == NULL) { + warning(_("unknown user '%s' in statoverride file"), str); + /* In chmod(2), -1 means "don't change file's uid" */ + uid = (uid_t)-1; + } else uid = pw->pw_uid; } return uid; @@ -77,15 +79,16 @@ statdb_parse_gid(const char *str) long int value; value = strtol(str + 1, &endptr, 10); - if (str + 1 == endptr || *endptr || value < 0) + if (str + 1 == endptr || *endptr || value < -1) ohshit(_("syntax error: invalid gid in statoverride file")); gid = (gid_t)value; } else { struct group* gr = getgrnam(str); - if (gr == NULL) - ohshit(_("syntax error: unknown group '%s' in statoverride file"), - str); - gid = gr->gr_gid; + if (gr == NULL) { + warning(_("unknown group '%s' in statoverride file"), str); + /* In chmod(2), -1 means "don't change file's gid" */ + gid = (gid_t)-1; + } else gid = gr->gr_gid; } return gid; @@ -170,8 +173,11 @@ ensure_statoverrides(void) ohshit(_("statoverride file is missing final newline")); /* Where to start next time around. */ nextline = ptr + 1; - if (ptr == thisline) - ohshit(_("statoverride file contains empty line")); + if (ptr == thisline) { + warning(_("statoverride file contains empty line")); + thisline = nextline; + continue; + } *ptr = '\0'; /* Extract the uid. */ @@ -204,6 +210,9 @@ ensure_statoverrides(void) *ptr = '\0'; fso->mode = statdb_parse_mode(thisline); + if ((fso->uid == (uid_t)-1 && fso->mode & S_ISUID) || + (fso->gid == (gid_t)-1 && fso->mode & S_ISGID)) + ohshit(_("statoverride demands setuid/setgid to an unknown user/group")); /* Move to the next bit */ thisline = ptr + 1; @@ -211,9 +220,16 @@ ensure_statoverrides(void) ohshit(_("unexpected end of line in statoverride file")); fnn = findnamenode(thisline, 0); - if (fnn->statoverride) - ohshit(_("multiple statusoverides present for file '%.250s'"), - thisline); + if (fnn->statoverride) { + if (fnn->statoverride->uid == fso->uid && + fnn->statoverride->gid == fso->gid && + fnn->statoverride->mode == fso->mode) + /* allow _identical_ overrides (with warning) */ + warning(_("multiple statusoverides present for file '%.250s'"), + thisline); + else ohshit(_( "multiple statusoverides present for file '%.250s'"), + thisline); + } fnn->statoverride = fso; /* Moving on.. */