[RFC] adding a --sysroot option

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

[RFC] adding a --sysroot option

Andrew Gregory
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
Reply | Threaded
Open this post in threaded view
|

Re: [RFC] adding a --sysroot option

Allan McRae
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
Reply | Threaded
Open this post in threaded view
|

Re: [RFC] adding a --sysroot option

Andrew Gregory
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
Reply | Threaded
Open this post in threaded view
|

Re: [RFC] adding a --sysroot option

Andrew Gregory
In reply to this post by Andrew Gregory
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
Reply | Threaded
Open this post in threaded view
|

Re: [RFC] adding a --sysroot option

Allan McRae
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
Reply | Threaded
Open this post in threaded view
|

[PATCH] add --sysroot option

Andrew Gregory
In reply to this post by Andrew Gregory
--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 <[hidden email]>
---

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