[pacman-dev] [RFC] adding a --sysroot option
pacman's --root option is regularly (mis)used to use pacman to manage a mounted guest system, typically one whose pacman installation is currently broken. We have a few configuration defaults in place to make this sort of work, but support is incomplete. Those defaults only actually take effect if the settings haven't been set in a configuration file, several options still default to the host system resources, and using the guest's pacman configuration requires updating all configured paths to the new mounted location. Adding a --sysroot/--chroot option would allow pacman to properly operate in a mounted guest system. At the moment, there are two ways we could accomplish this: prefix all paths with the sysroot or just call chroot(2). Obviously, the problem with chroot(2) is that it requires special privileges. Unfortunately, I think my symbolic user/group patch (https://patchwork.archlinux.org/patch/3694/) will require chroot to work properly as I can't find any other way to look up users/groups in a mounted guest. So, we may have to implement both approaches so that regular users can perform queries but privileged users can perform transactions with proper symbolic name support. apg
On 30/11/16 01:58, Andrew Gregory wrote:
pacman's --root option is regularly (mis)used to use pacman to manage a mounted guest system, typically one whose pacman installation is currently broken. We have a few configuration defaults in place to make this sort of work, but support is incomplete. Those defaults only actually take effect if the settings haven't been set in a configuration file, several options still default to the host system resources, and using the guest's pacman configuration requires updating all configured paths to the new mounted location.
What use would the current --root option be after this is implemented? Is this just a bug that --root should already be working exactly like proposed new option?
Adding a --sysroot/--chroot option would allow pacman to properly operate in a mounted guest system. At the moment, there are two ways we could accomplish this: prefix all paths with the sysroot or just call chroot(2). Obviously, the problem with chroot(2) is that it requires special privileges. Unfortunately, I think my symbolic user/group patch (https://patchwork.archlinux.org/patch/3694/) will require chroot to work properly as I can't find any other way to look up users/groups in a mounted guest. So, we may have to implement both approaches so that regular users can perform queries but privileged users can perform transactions with proper symbolic name support.
Don't we already chroot when running the install scripts? Is this just a case of extending that chroot to the entire operation? Allan
On 11/30/16 at 11:51am, Allan McRae wrote:
On 30/11/16 01:58, Andrew Gregory wrote:
pacman's --root option is regularly (mis)used to use pacman to manage a mounted guest system, typically one whose pacman installation is currently broken. We have a few configuration defaults in place to make this sort of work, but support is incomplete. Those defaults only actually take effect if the settings haven't been set in a configuration file, several options still default to the host system resources, and using the guest's pacman configuration requires updating all configured paths to the new mounted location.
What use would the current --root option be after this is implemented? Is this just a bug that --root should already be working exactly like proposed new option?
The --root option merely specifies where package files are installed. That is not necessarily the root directory of a system. --root can't work like the new option because other configured paths can be outside it and it can't affect which configuration files are read because it can be specified in a configuration file. --sysroot would be a command-line-only option and all paths would have to exist under it.
Adding a --sysroot/--chroot option would allow pacman to properly operate in a mounted guest system. At the moment, there are two ways we could accomplish this: prefix all paths with the sysroot or just call chroot(2). Obviously, the problem with chroot(2) is that it requires special privileges. Unfortunately, I think my symbolic user/group patch (https://patchwork.archlinux.org/patch/3694/) will require chroot to work properly as I can't find any other way to look up users/groups in a mounted guest. So, we may have to implement both approaches so that regular users can perform queries but privileged users can perform transactions with proper symbolic name support.
Don't we already chroot when running the install scripts? Is this just a case of extending that chroot to the entire operation?
We do chroot for scripts and hooks, but we chroot to --root, which could be a subdirectory inside --sysroot. apg
On 11/29/16 at 10:58am, Andrew Gregory wrote:
pacman's --root option is regularly (mis)used to use pacman to manage a mounted guest system, typically one whose pacman installation is currently broken. We have a few configuration defaults in place to make this sort of work, but support is incomplete. Those defaults only actually take effect if the settings haven't been set in a configuration file, several options still default to the host system resources, and using the guest's pacman configuration requires updating all configured paths to the new mounted location.
Adding a --sysroot/--chroot option would allow pacman to properly operate in a mounted guest system. At the moment, there are two ways we could accomplish this: prefix all paths with the sysroot or just call chroot(2). Obviously, the problem with chroot(2) is that it requires special privileges. Unfortunately, I think my symbolic user/group patch (https://patchwork.archlinux.org/patch/3694/) will require chroot to work properly as I can't find any other way to look up users/groups in a mounted guest. So, we may have to implement both approaches so that regular users can perform queries but privileged users can perform transactions with proper symbolic name support.
How should --sysroot handle user-provided paths on the command-line? Should they be treated as relative to --sysroot or the current root? Assuming that at some point this will be implemented using chroot(2) in at least some instances, all paths, including any package files given to -U, *must* exist under --sysroot. So, even though I think interpreting paths relative to the current root is more intuitive, it means extra work for us to determine if the path is accessible under --sysroot. apg
On 19/12/16 00:53, Andrew Gregory wrote:
On 11/29/16 at 10:58am, Andrew Gregory wrote:
pacman's --root option is regularly (mis)used to use pacman to manage a mounted guest system, typically one whose pacman installation is currently broken. We have a few configuration defaults in place to make this sort of work, but support is incomplete. Those defaults only actually take effect if the settings haven't been set in a configuration file, several options still default to the host system resources, and using the guest's pacman configuration requires updating all configured paths to the new mounted location.
Adding a --sysroot/--chroot option would allow pacman to properly operate in a mounted guest system. At the moment, there are two ways we could accomplish this: prefix all paths with the sysroot or just call chroot(2). Obviously, the problem with chroot(2) is that it requires special privileges. Unfortunately, I think my symbolic user/group patch (https://patchwork.archlinux.org/patch/3694/) will require chroot to work properly as I can't find any other way to look up users/groups in a mounted guest. So, we may have to implement both approaches so that regular users can perform queries but privileged users can perform transactions with proper symbolic name support.
How should --sysroot handle user-provided paths on the command-line? Should they be treated as relative to --sysroot or the current root? Assuming that at some point this will be implemented using chroot(2) in at least some instances, all paths, including any package files given to -U, *must* exist under --sysroot. So, even though I think interpreting paths relative to the current root is more intuitive, it means extra work for us to determine if the path is accessible under --sysroot.
My opinion with --sysroot, is that everything should be relative to the sysroot. As far as I can tell, that would be consistent with chroot, systemd-nspawn, etc. A
--root is not sufficient to properly operate on a mounted guest system. Using --root still uses the host system's configuration and there is no way to correctly use the guest configuration without manually modifying any Include directives. --sysroot provides an easier way to operate on a guest system by chrooting immediately after option parsing before configuration parsing or performing any operations. It is currently limited to the root user, but that's enough for restoring a guest system to a working state, which is the primary intended use case. Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com> --- I originally intended to put something in place to allow read-only operations for unprivileged users, but that is considerably more complex and, I think, a less important use case. doc/pacman.8.txt | 11 +++++++++-- src/pacman/conf.h | 2 ++ src/pacman/pacman.c | 24 ++++++++++++++++++------ src/pacman/util.c | 3 +++ 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt index f01f4aa4..d670e82a 100644 --- a/doc/pacman.8.txt +++ b/doc/pacman.8.txt @@ -136,11 +136,12 @@ Options *-r, \--root* <path>:: Specify an alternative installation root (default is `/`). This should not be used as a way to install software into `/usr/local` instead of - `/usr`. This option is used if you want to install a package on a - temporarily mounted partition that is "owned" by another system. + `/usr`. *NOTE*: If database path or log file are not specified on either the command line or in linkman:pacman.conf[5], their default location will be inside this root path. + *NOTE*: This option is not suitable for performing operations on a mounted + guest system. See '\--sysroot' instead. *-v, \--verbose*:: Output paths such as as the Root, Conf File, DB Path, Cache Dirs, etc. @@ -197,6 +198,12 @@ Options Disable defaults for low speed limit and timeout on downloads. Use this if you have issues downloading files with proxy and/or security gateway. +*\--sysroot* <dir>:: + Specify an alternative system root. Pacman will chroot and chdir into the + system root prior to running. This allows mounted guest systems to be + properly operated on. Any other paths given will be interpreted as relative + to the system root. Requires root privileges. + Transaction Options (apply to '-S', '-R' and '-U') -------------------------------------------------- diff --git a/src/pacman/conf.h b/src/pacman/conf.h index e67f7c51..53b44be6 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -67,6 +67,7 @@ typedef struct __config_t { char *dbpath; char *logfile; char *gpgdir; + char *sysroot; alpm_list_t *hookdirs; alpm_list_t *cachedirs; @@ -195,6 +196,7 @@ enum { OP_PRINT, OP_QUIET, OP_ROOT, + OP_SYSROOT, OP_RECURSIVE, OP_SEARCH, OP_REGEX, diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index 9d1cf6bb..605aec3e 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -214,6 +214,7 @@ static void usage(int op, const char * const myname) addlist(_(" -r, --root <path> set an alternate installation root\n")); addlist(_(" -v, --verbose be verbose\n")); addlist(_(" --arch <arch> set an alternate architecture\n")); + addlist(_(" --sysroot operate on a mounted guest system (root-only)\n")); addlist(_(" --cachedir <dir> set an alternate package cache location\n")); addlist(_(" --hookdir <dir> set an alternate hook location\n")); addlist(_(" --color <when> colorize the output\n")); @@ -447,6 +448,10 @@ static int parsearg_global(int opt) free(config->rootdir); config->rootdir = strdup(optarg); break; + case OP_SYSROOT: + free(config->sysroot); + config->sysroot = strdup(optarg); + break; case OP_DISABLEDLTIMEOUT: config->disable_dl_timeout = 1; break; @@ -917,6 +922,7 @@ static int parseargs(int argc, char *argv[]) {"print", no_argument, 0, OP_PRINT}, {"quiet", no_argument, 0, OP_QUIET}, {"root", required_argument, 0, OP_ROOT}, + {"sysroot", required_argument, 0, OP_SYSROOT}, {"recursive", no_argument, 0, OP_RECURSIVE}, {"search", no_argument, 0, OP_SEARCH}, {"regex", no_argument, 0, OP_REGEX}, @@ -1150,6 +1156,18 @@ int main(int argc, char *argv[]) cleanup(ret); } + /* check if we have sufficient permission for the requested operation */ + if(myuid > 0 && needs_root()) { + pm_printf(ALPM_LOG_ERROR, _("you cannot perform this operation unless you are root.\n")); + cleanup(EXIT_FAILURE); + } + + if(config->sysroot && (chroot(config->sysroot) != 0 || chdir("/") != 0)) { + pm_printf(ALPM_LOG_ERROR, + _("chroot to '%s' failed: (%s)\n"), config->sysroot, strerror(errno)); + cleanup(EXIT_FAILURE); + } + /* we support reading targets from stdin if a cmdline parameter is '-' */ if(alpm_list_find_str(pm_targets, "-")) { if(!isatty(fileno(stdin))) { @@ -1222,12 +1240,6 @@ int main(int argc, char *argv[]) config->logmask &= ~ALPM_LOG_WARNING; } - /* check if we have sufficient permission for the requested operation */ - if(myuid > 0 && needs_root()) { - pm_printf(ALPM_LOG_ERROR, _("you cannot perform this operation unless you are root.\n")); - cleanup(EXIT_FAILURE); - } - if(config->verbose > 0) { alpm_list_t *j; printf("Root : %s\n", alpm_option_get_root(config->handle)); diff --git a/src/pacman/util.c b/src/pacman/util.c index 64ea8c57..ae8a74d3 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -103,6 +103,9 @@ int trans_release(void) int needs_root(void) { + if(config->sysroot) { + return 1; + } switch(config->op) { case PM_OP_DATABASE: return !config->op_q_check; -- 2.12.2
participants (2)
-
Allan McRae
-
Andrew Gregory