rpm/safeugid.diff

215 lines
5.7 KiB
Diff

--- ../safeugid.diff 2019-10-02 13:37:13.191868203 +0200
+++ P 2019-10-02 13:36:09.036002978 +0200
@@ -0,0 +1,211 @@
+--- ./lib/rpmchroot.c.orig 2019-06-26 14:17:31.411985696 +0000
++++ ./lib/rpmchroot.c 2019-10-02 11:35:58.788024507 +0000
+@@ -126,6 +126,7 @@ int rpmChrootIn(void)
+
+ if (chdir("/") == 0 && chroot(rootState.rootDir) == 0) {
+ rootState.chrootDone = 1;
++ rpmugChroot(1);
+ } else {
+ rpmlog(RPMLOG_ERR, _("Unable to change root directory: %m\n"));
+ rc = -1;
+@@ -151,6 +152,7 @@ int rpmChrootOut(void)
+ } else if (rootState.chrootDone == 1) {
+ if (chroot(".") == 0 && fchdir(rootState.cwd) == 0) {
+ rootState.chrootDone = 0;
++ rpmugChroot(0);
+ } else {
+ rpmlog(RPMLOG_ERR, _("Unable to restore root directory: %m\n"));
+ rc = -1;
+--- ./lib/rpmug.c.orig 2019-06-26 14:17:31.418985685 +0000
++++ ./lib/rpmug.c 2019-10-02 11:35:58.788024507 +0000
+@@ -11,6 +11,47 @@
+ #include "lib/rpmug.h"
+ #include "debug.h"
+
++#if defined(__GLIBC__)
++
++static int inchroot;
++
++/*
++ * Unfortunatelly glibc caches nss/nscd data and there is no
++ * good way to flush those caches when we did a chroot(). Thus
++ * we need to parse /etc/passwd and /etc/group ourselfs.
++ */
++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;
++}
++#endif
++
+ /*
+ * These really ought to use hash tables. I just made the
+ * guess that most files would be owned by root or the same person/group
+@@ -44,17 +85,28 @@ int rpmugUid(const char * thisUname, uid
+ lastUnameAlloced = thisUnameLen + 10;
+ lastUname = xrealloc(lastUname, lastUnameAlloced); /* XXX memory leak */
+ }
+- strcpy(lastUname, thisUname);
+
+- pwent = getpwnam(thisUname);
+- if (pwent == NULL) {
+- /* FIX: shrug */
+- endpwent();
++#if defined(__GLIBC__)
++ if (inchroot) {
++ int uid = safe_lookup("/etc/passwd", thisUname);
++ if (uid < 0)
++ return -1;
++ lastUid = uid;
++ } else
++#endif
++ {
+ pwent = getpwnam(thisUname);
+- if (pwent == NULL) return -1;
++ if (pwent == NULL) {
++ /* FIX: shrug */
++ endpwent();
++ pwent = getpwnam(thisUname);
++ if (pwent == NULL) return -1;
++ }
++ lastUid = pwent->pw_uid;
+ }
+
+- lastUid = pwent->pw_uid;
++ strcpy(lastUname, thisUname);
++ lastUnameLen = thisUnameLen;
+ }
+
+ *uid = lastUid;
+@@ -87,18 +139,29 @@ int rpmugGid(const char * thisGname, gid
+ lastGnameAlloced = thisGnameLen + 10;
+ lastGname = xrealloc(lastGname, lastGnameAlloced); /* XXX memory leak */
+ }
+- strcpy(lastGname, thisGname);
+
+- grent = getgrnam(thisGname);
+- if (grent == NULL) {
+- /* FIX: shrug */
+- endgrent();
++#if defined(__GLIBC__)
++ if (inchroot) {
++ int gid = safe_lookup("/etc/group", thisGname);
++ if (gid < 0)
++ return -1;
++ lastGid = gid;
++ } else
++#endif
++ {
+ grent = getgrnam(thisGname);
+ if (grent == NULL) {
+- return -1;
++ /* FIX: shrug */
++ endgrent();
++ grent = getgrnam(thisGname);
++ if (grent == NULL) {
++ return -1;
++ }
+ }
++ lastGid = grent->gr_gid;
+ }
+- lastGid = grent->gr_gid;
++ strcpy(lastGname, thisGname);
++ lastGnameLen = thisGnameLen;
+ }
+
+ *gid = lastGid;
+@@ -110,7 +173,7 @@ const char * rpmugUname(uid_t uid)
+ {
+ static uid_t lastUid = (uid_t) -1;
+ static char * lastUname = NULL;
+- static size_t lastUnameLen = 0;
++ static size_t lastUnameAlloced = 0;
+
+ if (uid == (uid_t) -1) {
+ lastUid = (uid_t) -1;
+@@ -127,9 +190,9 @@ const char * rpmugUname(uid_t uid)
+
+ lastUid = uid;
+ len = strlen(pwent->pw_name);
+- if (lastUnameLen < len + 1) {
+- lastUnameLen = len + 20;
+- lastUname = xrealloc(lastUname, lastUnameLen);
++ if (lastUnameAlloced < len + 1) {
++ lastUnameAlloced = len + 20;
++ lastUname = xrealloc(lastUname, lastUnameAlloced);
+ }
+ strcpy(lastUname, pwent->pw_name);
+
+@@ -141,7 +204,7 @@ const char * rpmugGname(gid_t gid)
+ {
+ static gid_t lastGid = (gid_t) -1;
+ static char * lastGname = NULL;
+- static size_t lastGnameLen = 0;
++ static size_t lastGnameAlloced = 0;
+
+ if (gid == (gid_t) -1) {
+ lastGid = (gid_t) -1;
+@@ -158,9 +221,9 @@ const char * rpmugGname(gid_t gid)
+
+ lastGid = gid;
+ len = strlen(grent->gr_name);
+- if (lastGnameLen < len + 1) {
+- lastGnameLen = len + 20;
+- lastGname = xrealloc(lastGname, lastGnameLen);
++ if (lastGnameAlloced < len + 1) {
++ lastGnameAlloced = len + 20;
++ lastGname = xrealloc(lastGname, lastGnameAlloced);
+ }
+ strcpy(lastGname, grent->gr_name);
+
+@@ -192,3 +255,16 @@ void rpmugFree(void)
+ rpmugUname(-1);
+ rpmugGname(-1);
+ }
++
++void rpmugChroot(int in)
++{
++ /* tell libc to drop caches / file descriptors */
++ endpwent();
++ endgrent();
++ /* drop our own caches */
++ rpmugUid(NULL, NULL);
++ rpmugGid(NULL, NULL);
++#if defined(__GLIBC__)
++ inchroot = in;
++#endif
++}
+--- ./lib/rpmug.h.orig 2019-06-26 14:17:31.418985685 +0000
++++ ./lib/rpmug.h 2019-10-02 11:35:58.788024507 +0000
+@@ -15,4 +15,6 @@ int rpmugInit(void);
+
+ void rpmugFree(void);
+
++void rpmugChroot(int in);
++
+ #endif /* _RPMUG_H */