Marcus Rueckert
43997482be
-> OBS-URL: https://build.opensuse.org/request/show/70563 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/rpm?expand=0&rev=128
214 lines
5.5 KiB
Diff
214 lines
5.5 KiB
Diff
Work around glibc/nscd caching problems when doing 'rpm --root'.
|
|
|
|
--- ./lib/rpmchroot.c.orig 2011-05-12 08:26:10.000000000 +0000
|
|
+++ ./lib/rpmchroot.c 2011-05-12 08:28:32.000000000 +0000
|
|
@@ -66,6 +66,7 @@ int rpmChrootIn(void)
|
|
} else if (rootState.chrootDone == 0) {
|
|
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;
|
|
@@ -91,6 +92,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 2011-05-12 08:13:52.000000000 +0000
|
|
+++ ./lib/rpmug.c 2011-05-12 08:33:28.000000000 +0000
|
|
@@ -35,6 +35,47 @@ const char * rpmugStashStr(const char *s
|
|
return ret;
|
|
}
|
|
|
|
+#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
|
|
@@ -68,17 +109,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;
|
|
@@ -111,18 +163,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;
|
|
@@ -134,7 +197,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;
|
|
@@ -151,9 +214,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);
|
|
|
|
@@ -165,7 +228,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;
|
|
@@ -182,9 +245,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);
|
|
|
|
@@ -200,3 +263,16 @@ void rpmugFree(void)
|
|
rpmugGname(-1);
|
|
strStash = strCacheFree(strStash);
|
|
}
|
|
+
|
|
+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 2011-05-12 08:13:52.000000000 +0000
|
|
+++ ./lib/rpmug.h 2011-05-12 08:26:56.000000000 +0000
|
|
@@ -15,4 +15,6 @@ const char * rpmugGname(gid_t gid);
|
|
|
|
void rpmugFree(void);
|
|
|
|
+void rpmugChroot(int in);
|
|
+
|
|
#endif /* _RPMUG_H */
|