File safeugid.diff of Package rpm
--- lib/fsm.c.orig 2010-03-11 16:16:48.000000000 +0000
+++ lib/fsm.c 2010-03-11 17:00:46.000000000 +0000
@@ -760,14 +760,18 @@ int fsmMapAttrs(FSM_t fsm)
int i = fsm->ix;
if (fi && i >= 0 && i < fi->fc) {
+ rpmts ts = fsmGetTs(fsm);
mode_t perms = (S_ISDIR(st->st_mode) ? fi->dperms : fi->fperms);
mode_t finalMode = (fi->fmodes ? fi->fmodes[i] : perms);
dev_t finalRdev = (fi->frdevs ? fi->frdevs[i] : 0);
int_32 finalMtime = (fi->fmtimes ? fi->fmtimes[i] : 0);
+ int safe = rpmtsChrootDone(ts);
+ extern int unameToUid_safe(const char *, gid_t *, int);
+ extern int gnameToGid_safe(const char *, gid_t *, int);
uid_t uid = fi->uid;
gid_t gid = fi->gid;
- if (fi->fuser && unameToUid(fi->fuser[i], &uid)) {
+ if (fi->fuser && unameToUid_safe(fi->fuser[i], &uid, safe)) {
if (fsm->goal == FSM_PKGINSTALL)
rpmMessage(RPMMESS_WARNING,
_("user %s does not exist - using root\n"), fi->fuser[i]);
@@ -775,7 +779,7 @@ int fsmMapAttrs(FSM_t fsm)
finalMode &= ~S_ISUID; /* turn off suid bit */
}
- if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) {
+ if (fi->fgroup && gnameToGid_safe(fi->fgroup[i], &gid, safe)) {
if (fsm->goal == FSM_PKGINSTALL)
rpmMessage(RPMMESS_WARNING,
_("group %s does not exist - using root\n"), fi->fgroup[i]);
@@ -798,8 +802,7 @@ int fsmMapAttrs(FSM_t fsm)
if (fsm->mapFlags & CPIO_MAP_GID)
st->st_gid = gid;
- { rpmts ts = fsmGetTs(fsm);
-
+ {
/*
* Set file md5 (if not disabled).
*/
--- rpmio/ugid.c.orig 2010-03-11 15:40:31.000000000 +0000
+++ rpmio/ugid.c 2010-03-11 17:49:09.000000000 +0000
@@ -6,6 +6,37 @@
#include "ugid.h"
#include "debug.h"
+static int safe_lookup(const char * file, const char * name)
+{
+ FILE *fp;
+ int l;
+ char buf[4096], *p;
+
+ if (!name || !*name)
+ return -1;
+ l = strlen(name);
+ if ((fp = fopen(file, "r")) == 0)
+ return -1;
+ while ((p = fgets(buf, sizeof(buf), fp)) != 0) {
+ if (*p == '#')
+ continue;
+ while (*p && (*p == ' ' || *p == '\t'))
+ p++;
+ if (strncmp(p, name, l) != 0 || p[l] != ':')
+ continue;
+ p = strchr(p + l + 1, ':');
+ if (!p)
+ continue;
+ fclose(fp);
+ p++;
+ while (*p && (*p == ' ' || *p == '\t'))
+ p++;
+ return atoi(p);
+ }
+ fclose(fp);
+ return -1;
+}
+
/* unameToUid(), uidTouname() and the group variants are really poorly
implemented. They really ought to use hash tables. I just made the
guess that most files would be owned by root or the same person/group
@@ -13,11 +44,12 @@
is looked up via getpw() and getgr() functions. If this performs
too poorly I'll have to implement it properly :-( */
-int unameToUid(const char * thisUname, uid_t * uid)
+int unameToUid_safe(const char * thisUname, uid_t * uid, int safe)
{
/*@only@*/ static char * lastUname = NULL;
static size_t lastUnameLen = 0;
static size_t lastUnameAlloced;
+ static int lastUnameSafe;
static uid_t lastUid;
struct passwd * pwent;
size_t thisUnameLen;
@@ -31,6 +63,10 @@ int unameToUid(const char * thisUname, u
/*@=boundswrite@*/
return 0;
}
+ if (safe != lastUnameSafe) {
+ lastUnameLen = 0;
+ lastUnameSafe = safe;
+ }
thisUnameLen = strlen(thisUname);
if (lastUname == NULL || thisUnameLen != lastUnameLen ||
@@ -44,16 +80,23 @@ int unameToUid(const char * thisUname, u
strcpy(lastUname, thisUname);
/*@=boundswrite@*/
- pwent = getpwnam(thisUname);
- if (pwent == NULL) {
- /*@-internalglobs@*/ /* FIX: shrug */
- endpwent();
- /*@=internalglobs@*/
+ if (safe) {
+ int uid = safe_lookup("/etc/passwd", thisUname);
+ if (uid < 0)
+ return -1;
+ lastUid = (uid_t)uid;
+ } else {
pwent = getpwnam(thisUname);
- if (pwent == NULL) return -1;
- }
+ if (pwent == NULL) {
+ /*@-internalglobs@*/ /* FIX: shrug */
+ endpwent();
+ /*@=internalglobs@*/
+ pwent = getpwnam(thisUname);
+ if (pwent == NULL) return -1;
+ }
- lastUid = pwent->pw_uid;
+ lastUid = pwent->pw_uid;
+ }
}
/*@-boundswrite@*/
@@ -63,11 +106,17 @@ int unameToUid(const char * thisUname, u
return 0;
}
-int gnameToGid(const char * thisGname, gid_t * gid)
+int unameToUid(const char * thisUname, uid_t * uid)
+{
+ return unameToUid_safe(thisUname, uid, 0);
+}
+
+int gnameToGid_safe(const char * thisGname, gid_t * gid, int safe)
{
/*@only@*/ static char * lastGname = NULL;
static size_t lastGnameLen = 0;
static size_t lastGnameAlloced;
+ static int lastGnameSafe;
static gid_t lastGid;
size_t thisGnameLen;
struct group * grent;
@@ -81,6 +130,10 @@ int gnameToGid(const char * thisGname, g
/*@=boundswrite@*/
return 0;
}
+ if (safe != lastGnameSafe) {
+ lastGnameLen = 0;
+ lastGnameSafe = safe;
+ }
thisGnameLen = strlen(thisGname);
if (lastGname == NULL || thisGnameLen != lastGnameLen ||
@@ -94,30 +147,39 @@ int gnameToGid(const char * thisGname, g
strcpy(lastGname, thisGname);
/*@=boundswrite@*/
- grent = getgrnam(thisGname);
- if (grent == NULL) {
- /*@-internalglobs@*/ /* FIX: shrug */
- endgrent();
- /*@=internalglobs@*/
+ if (safe) {
+ int gid = safe_lookup("/etc/group", thisGname);
+ if (gid < 0)
+ return -1;
+ lastGid = (gid_t)gid;
+ } else {
grent = getgrnam(thisGname);
if (grent == NULL) {
- /* XXX The filesystem package needs group/lock w/o getgrnam. */
- if (strcmp(thisGname, "lock") == 0) {
-/*@-boundswrite@*/
- *gid = lastGid = 54;
-/*@=boundswrite@*/
- return 0;
- } else
- if (strcmp(thisGname, "mail") == 0) {
-/*@-boundswrite@*/
- *gid = lastGid = 12;
-/*@=boundswrite@*/
- return 0;
- } else
- return -1;
+ /*@-internalglobs@*/ /* FIX: shrug */
+ endgrent();
+ /*@=internalglobs@*/
+ grent = getgrnam(thisGname);
+ if (grent == NULL) {
+#if 0
+ /* XXX The filesystem package needs group/lock w/o getgrnam. */
+ if (strcmp(thisGname, "lock") == 0) {
+ /*@-boundswrite@*/
+ *gid = lastGid = 54;
+ /*@=boundswrite@*/
+ return 0;
+ } else
+ if (strcmp(thisGname, "mail") == 0) {
+ /*@-boundswrite@*/
+ *gid = lastGid = 12;
+ /*@=boundswrite@*/
+ return 0;
+ } else
+#endif
+ return -1;
+ }
}
+ lastGid = grent->gr_gid;
}
- lastGid = grent->gr_gid;
}
/*@-boundswrite@*/
@@ -127,6 +189,11 @@ int gnameToGid(const char * thisGname, g
return 0;
}
+int gnameToGid(const char * thisGname, gid_t * gid)
+{
+ return gnameToGid_safe(thisGname, gid, 0);
+}
+
char * uidToUname(uid_t uid)
{
static uid_t lastUid = (uid_t) -1;