--- rpm-4.4.6/rpmdb/db3.c.pix 2007-01-08 12:36:16.000000000 +0100 +++ rpm-4.4.6/rpmdb/db3.c 2007-01-08 12:36:22.000000000 +0100 @@ -77,6 +77,80 @@ }; /*@=fielduse@*/ +/*@unchecked@*/ /*@only@*/ /*@null@*/ +static const char * db3Cwd = NULL; +/*@unchecked@*/ +static int db3InRoot = 0; + +static void enterChroot(dbiIndex dbi, int from) + /*@globals db3Cwd, db3InRoot, internalState @*/ + /*@modifies db3Cwd, db3InRoot, internalState @*/ +{ + char * currDir = NULL; + int xx; + char * root = NULL; + + root = (dbi->dbi_root ? dbi->dbi_root : dbi->dbi_rpmdb->db_root); + + if (geteuid() || (root[0] == '/' && root[1] == '\0') || dbi->dbi_rpmdb->db_chrootDone || db3InRoot) + /* Nothing to do, was not already in chroot */ + return; + + { + int currDirLen = 0; + + do { + currDirLen += 128; + currDir = xrealloc(currDir, currDirLen); + memset(currDir, 0, currDirLen); + } while (getcwd(currDir, currDirLen) == NULL && errno == ERANGE); + } + + db3Cwd = currDir; + xx = chdir("/"); +/*@-superuser@*/ + xx = chroot(root); +/*@=superuser@*/ + if (xx != 0) { + int err = errno; + struct stat st; + if (Stat(root, &st) >= 0 && S_ISDIR(st.st_mode)) + rpmlog(RPMLOG_CRIT, _("only superuser is allowed to use --root\n")); + else + rpmlog(RPMLOG_CRIT, _("chroot failed, %s: %s\n"), root, strerror(err)); + abort(); + } + db3InRoot=from; +} + +static void leaveChroot(dbiIndex dbi, int from) + /*@globals db3Cwd, db3InRoot, internalState @*/ + /*@modifies db3Cwd, db3InRoot, internalState @*/ +{ + int xx; + char * root = NULL; + + root = (dbi->dbi_root ? dbi->dbi_root : dbi->dbi_rpmdb->db_root); + + if (geteuid() || (root[0] == '/' && root[1] == '\0') || dbi->dbi_rpmdb->db_chrootDone || !db3InRoot) + /* Nothing to do, not in chroot */ + return; + + if (from != db3InRoot) + return; + +/*@-superuser@*/ + xx = chroot("."); +/*@=superuser@*/ +assert(xx == 0); + if (db3Cwd != NULL) { + xx = chdir(db3Cwd); + db3Cwd = _free(db3Cwd); + } + + db3InRoot = 0; +} + #ifdef NOTNOW static const char * bfstring(unsigned int x, const char * xbf) { @@ -179,9 +253,11 @@ rpmdb rpmdb = dbi->dbi_rpmdb; DB_ENV * dbenv = rpmdb->db_dbenv; int rc; + int FROMCHROOT = __LINE__; if (dbenv == NULL) return 0; + enterChroot(dbi, FROMCHROOT); rc = dbenv->close(dbenv, 0); rc = cvtdberr(dbi, "dbenv->close", rc, _debug); @@ -209,6 +285,7 @@ dbhome, dbfile); } + leaveChroot(dbi, FROMCHROOT); return rc; } @@ -282,6 +359,7 @@ DB_ENV *dbenv = NULL; int eflags; int rc; + int FROMCHROOT = __LINE__; if (dbenvp == NULL) return 1; @@ -295,6 +373,8 @@ eflags = (dbi->dbi_oeflags | dbi->dbi_eflags); if (eflags & DB_JOINENV) eflags &= DB_JOINENV; + enterChroot(dbi, FROMCHROOT); + if (dbfile) rpmMessage(RPMMESS_DEBUG, _("opening db environment %s/%s %s\n"), dbhome, dbfile, prDbiOpenFlags(eflags, 1)); @@ -379,7 +459,7 @@ root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root); /*@-boundsread@*/ - if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone) + if (!geteuid() || (root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone) root = NULL; /*@=boundsread@*/ /*@-mods@*/ @@ -442,6 +522,7 @@ /*@-boundswrite@*/ *dbenvp = dbenv; /*@=boundswrite@*/ + leaveChroot(dbi, FROMCHROOT); return 0; @@ -451,6 +532,7 @@ xx = dbenv->close(dbenv, 0); xx = cvtdberr(dbi, "dbenv->close", xx, _debug); } + leaveChroot(dbi, FROMCHROOT); return rc; } /*@=moduncon@*/ @@ -462,6 +544,9 @@ DB * db = dbi->dbi_db; int rc = 0; int _printit; + int FROMCHROOT = __LINE__; + + enterChroot(dbi, FROMCHROOT); if (db != NULL) rc = db->sync(db, flags); @@ -472,6 +557,7 @@ _printit = (rc == DB_INCOMPLETE ? 0 : _debug); #endif rc = cvtdberr(dbi, "db->sync", rc, _printit); + leaveChroot(dbi, FROMCHROOT); return rc; } @@ -481,13 +567,15 @@ /*@modifies *dbcp, fileSystem @*/ { int rc; - + int FROMCHROOT = __LINE__; + enterChroot(dbi, FROMCHROOT); /*@-boundswrite@*/ if (dbcp) *dbcp = NULL; /*@=boundswrite@*/ rc = dbcursor->c_dup(dbcursor, dbcp, flags); rc = cvtdberr(dbi, "dbcursor->c_dup", rc, _debug); /*@-nullstate @*/ /* FIX: *dbcp can be NULL */ + leaveChroot(dbi, FROMCHROOT); return rc; /*@=nullstate @*/ } @@ -499,12 +587,15 @@ /*@modifies dbi, fileSystem @*/ { int rc = -2; + int FROMCHROOT = __LINE__; + enterChroot(dbi, FROMCHROOT); /* XXX db3copen error pathways come through here. */ if (dbcursor != NULL) { rc = dbcursor->c_close(dbcursor); rc = cvtdberr(dbi, "dbcursor->c_close", rc, _debug); } + leaveChroot(dbi, FROMCHROOT); return rc; } /*@=mustmod@*/ @@ -518,9 +609,11 @@ DBC * dbcursor = NULL; int flags; int rc; + int FROMCHROOT = __LINE__; /* XXX DB_WRITECURSOR cannot be used with sunrpc dbenv. */ assert(db != NULL); + enterChroot(dbi, FROMCHROOT); if ((dbiflags & DB_WRITECURSOR) && (dbi->dbi_eflags & DB_INIT_CDB) && !(dbi->dbi_oflags & DB_RDONLY)) { @@ -535,7 +628,8 @@ /*@-boundswrite -onlytrans@*/ *dbcp = dbcursor; /*@=boundswrite =onlytrans@*/ else (void) db3cclose(dbi, dbcursor, 0); - + + leaveChroot(dbi, FROMCHROOT); return rc; } @@ -546,8 +640,10 @@ { DB * db = dbi->dbi_db; int rc; + int FROMCHROOT = __LINE__; assert(db != NULL); + enterChroot(dbi, FROMCHROOT); if (dbcursor == NULL) { rc = db->put(db, dbi->dbi_txnid, key, data, 0); rc = cvtdberr(dbi, "db->put", rc, _debug); @@ -555,7 +651,7 @@ rc = dbcursor->c_put(dbcursor, key, data, DB_KEYLAST); rc = cvtdberr(dbi, "dbcursor->c_put", rc, _debug); } - + leaveChroot(dbi, FROMCHROOT); return rc; } @@ -567,8 +663,10 @@ { DB * db = dbi->dbi_db; int rc; + int FROMCHROOT = __LINE__; assert(db != NULL); + enterChroot(dbi, FROMCHROOT); if (dbcursor == NULL) { rc = db->del(db, dbi->dbi_txnid, key, flags); rc = cvtdberr(dbi, "db->del", rc, _debug); @@ -587,6 +685,7 @@ } } + leaveChroot(dbi, FROMCHROOT); return rc; } /*@=mustmod@*/ @@ -600,8 +699,10 @@ DB * db = dbi->dbi_db; int _printit; int rc; + int FROMCHROOT = __LINE__; assert(db != NULL); + enterChroot(dbi, FROMCHROOT); if (dbcursor == NULL) { /* XXX duplicates require cursors. */ rc = db->get(db, dbi->dbi_txnid, key, data, 0); @@ -616,6 +717,7 @@ rc = cvtdberr(dbi, "dbcursor->c_get", rc, _printit); } + leaveChroot(dbi, FROMCHROOT); return rc; } /*@=mustmod@*/ @@ -629,16 +731,19 @@ DB * db = dbi->dbi_db; int _printit; int rc; + int FROMCHROOT = __LINE__; assert(db != NULL); assert(dbcursor != NULL); + enterChroot(dbi, FROMCHROOT); /* XXX db3 does DB_FIRST on uninitialized cursor */ rc = dbcursor->c_pget(dbcursor, key, pkey, data, flags); /* XXX DB_NOTFOUND can be returned */ _printit = (rc == DB_NOTFOUND ? 0 : _debug); rc = cvtdberr(dbi, "dbcursor->c_pget", rc, _printit); + leaveChroot(dbi, FROMCHROOT); return rc; } /*@=mustmod@*/ @@ -651,10 +756,13 @@ { db_recno_t count = 0; int rc = 0; + int FROMCHROOT = __LINE__; flags = 0; + enterChroot(dbi, FROMCHROOT); rc = dbcursor->c_count(dbcursor, &count, flags); rc = cvtdberr(dbi, "dbcursor->c_count", rc, _debug); + leaveChroot(dbi, FROMCHROOT); if (rc) return rc; /*@-boundswrite@*/ if (countp) *countp = count; @@ -667,7 +775,9 @@ { DB * db = dbi->dbi_db; int rc = 0; + int FROMCHROOT = __LINE__; + enterChroot(dbi, FROMCHROOT); if (db != NULL) { #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && DB_VERSION_PATCH == 11) \ || (DB_VERSION_MAJOR == 4) @@ -680,6 +790,7 @@ #endif } + leaveChroot(dbi, FROMCHROOT); return rc; } @@ -692,8 +803,10 @@ DB_TXN * txnid = NULL; #endif int rc = 0; + int FROMCHROOT = __LINE__; assert(db != NULL); + enterChroot(dbi, FROMCHROOT); #if defined(DB_FAST_STAT) if (flags) flags = DB_FAST_STAT; @@ -712,6 +825,7 @@ rc = db->stat(db, &dbi->dbi_stats, NULL, flags); #endif rc = cvtdberr(dbi, "db->stat", rc, _debug); + leaveChroot(dbi, FROMCHROOT); return rc; } @@ -725,7 +839,9 @@ DB * db = dbi->dbi_db; DB * secondary = dbisecondary->dbi_db; int rc; + int FROMCHROOT = __LINE__; + enterChroot(dbi, FROMCHROOT); /*@-moduncon@*/ /* FIX: annotate db3 methods */ #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1) DB_TXN * txnid = NULL; @@ -738,6 +854,7 @@ #endif /*@=moduncon@*/ rc = cvtdberr(dbi, "db->associate", rc, _debug); + leaveChroot(dbi, FROMCHROOT); return rc; } /*@=mustmod@*/ @@ -750,12 +867,15 @@ { DB * db = dbi->dbi_db; int rc; + int FROMCHROOT = __LINE__; assert(db != NULL); + enterChroot(dbi, FROMCHROOT); /*@-moduncon@*/ /* FIX: annotate db3 methods */ rc = db->join(db, curslist, dbcp, flags); /*@=moduncon@*/ rc = cvtdberr(dbi, "db->join", rc, _debug); + leaveChroot(dbi, FROMCHROOT); return rc; } /*@=mustmod@*/ @@ -776,6 +896,7 @@ DB * db = dbi->dbi_db; int _printit; int rc = 0, xx; + int FROMCHROOT = __LINE__; flags = 0; /* XXX unused */ @@ -784,11 +905,12 @@ */ root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root); /*@-boundsread@*/ - if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone) + if (!geteuid() || (root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone) root = NULL; /*@=boundsread@*/ home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home); + enterChroot(dbi, FROMCHROOT); /* * Either the root or directory components may be a URL. Concatenate, * convert the URL to a path, and add the name of the file. @@ -903,6 +1025,7 @@ } exit: + leaveChroot(dbi, FROMCHROOT); dbi->dbi_db = NULL; urlfn = _free(urlfn); @@ -938,12 +1061,13 @@ #endif u_int32_t oflags; int _printit; + int FROMCHROOT = __LINE__; /*@-boundswrite@*/ if (dbip) *dbip = NULL; /*@=boundswrite@*/ - + /* * Parse db configuration parameters. */ @@ -960,8 +1084,9 @@ */ root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root); /*@-boundsread@*/ - if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone) + if (!geteuid() || (root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone) root = NULL; + enterChroot(dbi, FROMCHROOT); /*@=boundsread@*/ home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home); @@ -1162,6 +1287,7 @@ /*@=mods@*/ } + /* enterChroot(dbi); */ rpmMessage(RPMMESS_DEBUG, _("opening db index %s/%s %s mode=0x%x\n"), dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)), prDbiOpenFlags(oflags, 0), dbi->dbi_mode); @@ -1432,6 +1558,7 @@ urlfn = _free(urlfn); + leaveChroot(dbi, FROMCHROOT); /*@-nullstate -compmempass@*/ return rc; /*@=nullstate =compmempass@*/