[LTP] [PATCH] save_restore: Check whether path is writable

Jan Stancek jstancek@redhat.com
Mon Oct 24 09:16:03 CEST 2022


On Fri, Oct 21, 2022 at 10:35 PM Petr Vorel <pvorel@suse.cz> wrote:
>
> Hi Martin,
>
> [ Cc Jan, who implemented the original behavior ]
>
> > Tests using the .save_restore functionality currently cannot run
> > without root privileges at all because the test will write
> > into the path at least at the end and trigger error, even when
> > the config paths are flagged as optional.

Problem description makes it sound like this issue affects all 3 types
of config options. Isn't the problem affecting only optional config paths?

Having entry with "(no prefix)" or "!" in save_restore implies that
test wants to write to that path - if we TCONF on root privileges or
read/write access probably doesn't make much difference - we can't
continue.

For "?" prefix, I agree that since its optional, test should be able
to run cleanly without root privileges.

> Check whether .save_restore
> > paths are writable and handle negative result the same way as if
> > the path does not exist.

Do you mean for "?" prefix only?

>
> > Signed-off-by: Martin Doucha <mdoucha@suse.cz>
> > ---
>
> > This is the first part of sysfile handling fixes to allow running some
> > tests without root privileges again. I think this is a good enough solution
> > for the save_restore part but we should discuss a few open questions first:
>
> > 1) Is it OK to fail early during sysfile save when the test would otherwise
> >    run fine but throw TWARN at the end because the sysfile is read-only?
> I don't think that would be a good change.

For optional path, if test can't read/write it (b/o of no root privileges),
I think library shouldn't try to save it - then that would also skip
attempt to restore it.

>
> > 2) Should the '?' flag skip read-only files as if they don't exist?
I think yes. If we can't restore those files, that means test shouldn't
be able to change those and we don't need to worry about saving them.

> >    Alternatively, we could still let the '?' flag fail trying to write
> >    into read-only sysfiles and instead introduce a new flag for cases where
> >    read-only file should be skipped.
> Looking at files which use '?', some of them (mostly network related, I guess
> written/rewritten by Martin) use SAFE_TRY_FILE_PRINTF() on
> /proc/sys/user/max_user_namespaces. It looks to me these need to to skip
> read-only files, i.e. define new flag with this behavior.
>
>
> Kind regards,
> Petr
>
> >  doc/c-test-api.txt | 11 +++++------
> >  lib/tst_sys_conf.c | 32 ++++++++++++++++++++++----------
> >  2 files changed, 27 insertions(+), 16 deletions(-)
>
> > diff --git a/doc/c-test-api.txt b/doc/c-test-api.txt
> > index 64ee3397f..0f36b5a67 100644
> > --- a/doc/c-test-api.txt
> > +++ b/doc/c-test-api.txt
> > @@ -1601,13 +1601,12 @@ If non-NULL value is passed it is written to the respective file at
> >  the beginning of the test. Only the first line of a specified file
> >  is saved and restored.
>
> > -Pathnames can be optionally prefixed to specify how strictly (during
> > -'store') are handled errors:
> > +Pathnames can be optionally prefixed to specify how to handle missing or
> > +read-only files:
>
> > -* (no prefix) - test ends with 'TCONF', if file doesn't exist
> > -* '?'         - test prints info message and continues,
> > -                if file doesn't exist or open/read fails
> > -* '!'         - test ends with 'TBROK', if file doesn't exist
> > +* (no prefix) - test ends with 'TCONF'
> > +* '?'         - test prints info message and continues, even on read error
> > +* '!'         - test ends with 'TBROK'
>
> >  'restore' is always strict and will TWARN if it encounters any error.
>
> > diff --git a/lib/tst_sys_conf.c b/lib/tst_sys_conf.c
> > index 003698825..1e381a249 100644
> > --- a/lib/tst_sys_conf.c
> > +++ b/lib/tst_sys_conf.c
> > @@ -20,6 +20,22 @@ struct tst_sys_conf {
>
> >  static struct tst_sys_conf *save_restore_data;
>
> > +static void print_access_error(char flag, const char *err, const char *path)
> > +{
> > +     switch (flag) {
> > +     case '?':
> > +             tst_res(TINFO, "%s: '%s'", err, path);
> > +             break;
> > +
> > +     case '!':
> > +             tst_brk(TBROK|TERRNO, "%s: '%s'", err, path);
> > +             break;
> > +
> > +     default:
> > +             tst_brk(TCONF|TERRNO, "%s: '%s'", err, path);
> > +     }
> > +}
> > +
> >  void tst_sys_conf_dump(void)
> >  {
> >       struct tst_sys_conf *i;
> > @@ -59,16 +75,12 @@ int tst_sys_conf_save(const char *path)
> >               path++;
>
> >       if (access(path, F_OK) != 0) {
> > -             switch (flag) {
> > -             case '?':
> > -                     tst_res(TINFO, "Path not found: '%s'", path);
> > -                     break;
> > -             case '!':
> > -                     tst_brk(TBROK|TERRNO, "Path not found: '%s'", path);
> > -                     break;
> > -             default:
> > -                     tst_brk(TCONF|TERRNO, "Path not found: '%s'", path);
> > -             }
> > +             print_access_error(flag, "Path not found", path);
> > +             return 1;
> > +     }
> > +
> > +     if (access(path, W_OK) != 0) {
> > +             print_access_error(flag, "Path is not writable", path);
> >               return 1;
> >       }
>



More information about the ltp mailing list