From 8c11c15b7546585904430803101d69754a86fb1b Mon Sep 17 00:00:00 2001 From: Gordon Hecker Date: Thu, 2 Apr 2009 17:47:20 +0200 Subject: [PATCH] move chroot marker out of the chroot environment, fixing a possible deadlock situation Signed-off-by: Gordon Hecker --- generic/e2-su-2.2.c | 138 +++++++++++++++++++++++++++++++++++++++++++- local/e2build.lua | 45 +++++++++------ 2 files changed, 162 insertions(+), 21 deletions(-) diff --git a/generic/e2-su-2.2.c b/generic/e2-su-2.2.c index de9b7aa..8476eac 100644 --- a/generic/e2-su-2.2.c +++ b/generic/e2-su-2.2.c @@ -25,6 +25,25 @@ along with this program. If not, see . */ +/* chroot layout used with the _2_2 postfix commands + * call with e2-su-2.2 ... + * path/emlix-chroot - chroot marker file + * path/ - chroot environment + * + * This layout is broken: the chroot marker file can be deleted in chroot + * and early when removing chroot is not fully done. + * In that case e2factory refuses to use and even delete the chroot + * environment, leaving the user with a chroot environment that only + * root may delete. + * + * The new chroot layout fixes this: + * + * chroot layout used with the _2_3 postfix commands + * call with e2-su-2.2 ... + * base/e2factory-chroot - chroot marker file + * base/chroot/ - chroot environment + */ + #include #include #include @@ -109,6 +128,17 @@ void assert_chroot_environment(char *path) return; } +void assert_chroot_environment_2_3(char *base) +{ + char name[PATH_MAX]; + snprintf(name, sizeof(name), "%s/e2factory-chroot", base); + name[sizeof(name)-1]=0; + if(access(name, R_OK)) { + perr("not a chroot environment"); + } + return; +} + int main(int argc, char *argv[]) { int rc; @@ -119,8 +149,6 @@ int main(int argc, char *argv[]) perr("too many arguments"); } char *cmd = argv[1]; - char *path = argv[2]; - assert_chroot_environment(path); if(!strcmp(cmd, "chroot_2_2")) { /* chroot_2_2 ... */ int i; @@ -128,6 +156,8 @@ int main(int argc, char *argv[]) if(argc < 3) { perr("too few arguments"); } + char *path = argv[2]; + assert_chroot_environment(path); arg[0] = basename(chroot_tool); arg[1] = path; for (i=3; i < argc; i++) { @@ -145,6 +175,8 @@ int main(int argc, char *argv[]) if(argc != 5) { perr("wrong number of arguments"); } + char *path = argv[2]; + assert_chroot_environment(path); char *tartype = argv[3]; char *file = argv[4]; char *tararg = NULL; @@ -174,6 +206,8 @@ int main(int argc, char *argv[]) if(argc != 3) { perr("wrong number of arguments"); } + char *path = argv[2]; + assert_chroot_environment(path); arg[0] = basename(chown_tool); arg[1] = "root:root"; arg[2] = path; @@ -189,6 +223,106 @@ int main(int argc, char *argv[]) if(argc != 3) { perr("wrong number of arguments"); } + char *path = argv[2]; + assert_chroot_environment(path); + arg[0] = basename(rm_tool); + arg[1] = "-r"; + arg[2] = "-f"; + arg[3] = path; + arg[4] = NULL; + print_arg(arg); + setuid_root(); + rc = execv(rm_tool, arg); + perror("can't exec"); + exit(99); + } else if(!strcmp(cmd, "chroot_2_3")) { + /* chroot_2_3 ... */ + int i; + char *arg[256]; + if(argc < 3) { + perr("too few arguments"); + } + char *base = argv[2]; + char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s/chroot", base); + path[sizeof(path)-1] = 0; + assert_chroot_environment_2_3(base); + arg[0] = basename(chroot_tool); + arg[1] = path; + for (i=3; i < argc; i++) { + arg[i-1] = argv[i]; + } + arg[i-1] = 0; + print_arg(arg); + setuid_root(); + rc = execv(chroot_tool, arg); + perror("can't exec"); + exit(99); + } else if(!strcmp(cmd, "extract_tar_2_3")) { + /* extract_tar_2_3 */ + char *arg[256]; + if(argc != 5) { + perr("wrong number of arguments"); + } + char *base = argv[2]; + assert_chroot_environment_2_3(base); + char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s/chroot", base); + path[sizeof(path)-1] = 0; + char *tartype = argv[3]; + char *file = argv[4]; + char *tararg = NULL; + if(!strcmp(tartype, "tar.gz")) { + tararg = "-xzf"; + } else if(!strcmp(tartype, "tar.bz2")) { + tararg = "-xjf"; + } else if(!strcmp(tartype, "tar")) { + tararg = "-xf"; + } else { + perr("wrong tararg argument"); + } + arg[0] = basename(tar_tool); + arg[1] = "-C"; + arg[2] = path; + arg[3] = tararg; + arg[4] = file; + arg[5] = NULL; + print_arg(arg); + setuid_root(); + rc = execv(tar_tool, arg); + perror("can't exec"); + exit(99); + } else if(!strcmp(cmd, "set_permissions_2_3")) { + /* set_permissions_2_3 */ + char *arg[256]; + if(argc != 3) { + perr("wrong number of arguments"); + } + char *base = argv[2]; + assert_chroot_environment_2_3(base); + char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s/chroot", base); + path[sizeof(path)-1] = 0; + arg[0] = basename(chown_tool); + arg[1] = "root:root"; + arg[2] = path; + arg[3] = NULL; + print_arg(arg); + setuid_root(); + rc = execv(chown_tool, arg); + perror("can't exec"); + exit(99); + } else if(!strcmp(cmd, "remove_chroot_2_3")) { + /* remove_chroot_2_3 */ + char *arg[256]; + if(argc != 3) { + perr("wrong number of arguments"); + } + char *base = argv[2]; + assert_chroot_environment_2_3(base); + char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s/chroot", base); + path[sizeof(path)-1] = 0; arg[0] = basename(rm_tool); arg[1] = "-r"; arg[2] = "-f"; diff --git a/local/e2build.lua b/local/e2build.lua index 5057160..c403563 100644 --- a/local/e2build.lua +++ b/local/e2build.lua @@ -131,7 +131,9 @@ end -- @field mode table: the build mode policy -- @field release id string: the release name -- @field info table: the info table +-- @field base string: path to the build directory -- @field c string: path to the chroot +-- @field chroot_marker string: path to chroot marker file -- @field T string: absolute path to the temporary build directory -- inside chroot -- @field Tc string: same as c.T but relative to c @@ -168,7 +170,9 @@ function e2build.build_config(info, r) tab.mode = nil -- XXX tab.location = nil -- XXX info.project_location tab.release_id = nil -- XXX release_id - tab.c = string.format("%s/%s/%s/chroot", tmpdir, project, r) + tab.base = string.format("%s/%s/%s", tmpdir, project, r) + tab.c = string.format("%s/chroot", tab.base) + tab.chroot_marker = string.format("%s/e2factory-chroot", tab.base) tab.T = string.format("%s/%s/%s/chroot/%s", tmpdir, project, r, builddir) tab.Tc = string.format("/%s", builddir) tab.r = string.format("%s", r) @@ -213,13 +217,13 @@ function e2build.setup_chroot(info, r, return_flags) if not rc then return false, e:cat(re) end - local rc, re = e2lib.touch(res.build_config.c .. "/emlix-chroot") + local rc, re = e2lib.touch(res.build_config.chroot_marker) if not rc then return false, e:cat(re) end - -- e2-su set_permissions_2_2 - local args = string.format("set_permissions_2_2 '%s'", - res.build_config.c) + -- e2-su set_permissions_2_3 + local args = string.format("set_permissions_2_3 '%s'", + res.build_config.base) local rc, re = e2lib.e2_su_2_2(args) if not rc then return false, e:cat(re) @@ -247,9 +251,9 @@ function e2build.setup_chroot(info, r, return_flags) e:append("unknown archive type for chroot file: %s", path) return false, e end - -- e2-su extract_tar_2_2 - local args = string.format("extract_tar_2_2 '%s' '%s' '%s'", - res.build_config.c, tartype, path) + -- e2-su extract_tar_2_3 + local args = string.format("extract_tar_2_3 '%s' '%s' '%s'", + res.build_config.base, tartype, path) local rc, re = e2lib.e2_su_2_2(args) if not rc then return false, e:cat(re) @@ -270,9 +274,9 @@ function e2build.enter_playground(info, r, chroot_command) e2lib.log(4, "entering playground for " .. r .. " ...") local term = e2lib.terminal local e2_su = transport.get_tool("e2-su-2.2") - local cmd = string.format("%s %s chroot_2_2 '%s' %s", + local cmd = string.format("%s %s chroot_2_3 '%s' %s", res.build_config.chroot_call_prefix, e2_su, - res.build_config.c, chroot_command) + res.build_config.base, chroot_command) os.execute(cmd) -- return code depends on user commands. Ignore. return true, nil @@ -283,14 +287,14 @@ function e2build.fix_permissions(info, r, return_flags) local rc, re local e = new_error("fixing permissions failed") e2lib.log(3, "fix permissions") - local args = string.format("chroot_2_2 '%s' chown -R root:root '%s'", - res.build_config.c, res.build_config.Tc) + local args = string.format("chroot_2_3 '%s' chown -R root:root '%s'", + res.build_config.base, res.build_config.Tc) rc, re = e2lib.e2_su_2_2(args) if not rc then return false, e:cat(re) end - local args = string.format("chroot_2_2 '%s' chmod -R u=rwX,go=rX '%s'", - res.build_config.c, res.build_config.Tc) + local args = string.format("chroot_2_3 '%s' chmod -R u=rwX,go=rX '%s'", + res.build_config.base, res.build_config.Tc) rc, re = e2lib.e2_su_2_2(args) if not rc then return false, e:cat(re) @@ -318,9 +322,9 @@ function e2build.runbuild(info, r, return_flags) res.build_config.Tc, res.build_config.scriptdir, res.build_config.build_driver_file) local e2_su = transport.get_tool("e2-su-2.2") - local cmd = string.format("%s %s chroot_2_2 '%s' %s", + local cmd = string.format("%s %s chroot_2_3 '%s' %s", res.build_config.chroot_call_prefix, e2_su, - res.build_config.c, runbuild) + res.build_config.base, runbuild) -- the build log is written to an external logfile local out = luafile.open(res.build_config.buildlog, "w") local function logto(output) @@ -346,11 +350,15 @@ function e2build.chroot_cleanup(info, r, return_flags) if res.keep_chroot then return true, nil end - local args = string.format("remove_chroot_2_2 '%s'", res.build_config.c) + local args = string.format("remove_chroot_2_3 '%s'", res.build_config.base) local rc, re = e2lib.e2_su_2_2(args) if not rc then return e:cat(re) end + rc, re = e2lib.rm(res.build_config.chroot_marker) + if not rc then + return false, e:cat(re) + end local f = string.format("%s/playground", info.root) local s = e2util.stat(f) if s and s.type == "symbolic-link" then @@ -376,8 +384,7 @@ end -- @return bool function e2build.chroot_exists(info, r) local res = info.results[r] - local f = string.format("%s/emlix-chroot", res.build_config.c) - return e2lib.isfile(f) + return e2lib.isfile(res.build_config.chroot_marker) end function e2build.sources(info, r, return_flags) -- 2.39.5