Sophie

Sophie

distrib > Mandriva > 2007.1 > i586 > by-pkgid > 2e20fbe220a1d0f48a15d5008a7dd680 > files > 20

rpm-4.4.6-22.1mdv2007.1.src.rpm

--- 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@*/