On Thu, Nov 05, 2015 at 04:52:29PM +0100, Gregor Best wrote:
> Hi people,
> 
> kvm_mkdb currently gets killed during an fchown if /var is full and the
> file containing the kernel namelist doesn't exist. This can be
> reproduced like this:
> 
>       # rm /var/db/kvm_bsd.db
>       # kvm_mkdb
> 
>       /var: write failed, file system is full
> 
>       /var: write failed, file system is full
>       kvm_mkdb: can't dbclose /var/db/kvm_bsd.tmp: No space left on device
>       kvm_mkdb: will try again using /bsd instead
>       Abort trap
> 
> The issue is a missing "fattr" pledge in kvm_mkdb.c line 173, and the
> fact that the function kvm_mkdb() can be called more than once.
> 
> The patch below the signature adds the missing pledge and moves the
> pledge() call further up into main(). This way, all invocations of
> kvm_mkdb() are completely covered by the pledge.
> 
> -- 
>       Gregor
> 
> Index: kvm_mkdb.c
> ===================================================================
> RCS file: /mnt/media/cvs/src/usr.sbin/kvm_mkdb/kvm_mkdb.c,v
> retrieving revision 1.24
> diff -u -p -r1.24 kvm_mkdb.c
> --- kvm_mkdb.c        16 Oct 2015 13:37:44 -0000      1.24
> +++ kvm_mkdb.c        5 Nov 2015 15:50:35 -0000
> @@ -98,6 +98,9 @@ main(int argc, char *argv[])
>       if (argc > 1)
>               usage();
>  
> +     if (pledge("stdio rpath wpath cpath fattr flock", NULL) == -1)
> +             err(1, "pledge");
> +
>       /* If no kernel specified use _PATH_KSYMS and fall back to _PATH_UNIX */
>       if (argc > 0) {
>               nlistpath = argv[0];
> @@ -168,10 +171,6 @@ kvm_mkdb(int fd, const char *dbdir, char
>               (void)unlink(dbtemp);
>               return(1);
>       }
> -
> -     /* rename() later */
> -     if (pledge("stdio rpath wpath cpath flock", NULL) == -1)
> -             err(1, "pledge");
>  
>       if (create_knlist(nlistpath, fd, db) != 0) {
>               warn("cannot determine executable type of %s", nlistpath);
> 

When rebooting I now get the following errors from the rc script:

[...]
checking quotas: done.
kvm_mkdb: can't chown /var/db/kvm_bsd.tmp: Operation not permitted
kvm_mkdb: will try again using /bsd instead
kvm_mkdb: can't chown /var/db/kvm_bsd.tmp: Operation not permitted
clearing /tmp
[...]

The problem is that the kernel does not allow changing the gid of an fd
or file after pledge was called, so we can't pledge before calling
kvm_mkdb() the first time.

Moving the pledge back to where it was would fix this problem, but I
don't think the problem reported by Gregor will be solved by that: the
kvm_mkdb() call will still fail, but at least kvm_mkdb won't be killed.

Index: usr.sbin/kvm_mkdb/kvm_mkdb.c
===================================================================
RCS file: /cvs/src/usr.sbin/kvm_mkdb/kvm_mkdb.c,v
retrieving revision 1.25
diff -u -p -r1.25 kvm_mkdb.c
--- usr.sbin/kvm_mkdb/kvm_mkdb.c        5 Nov 2015 16:15:47 -0000       1.25
+++ usr.sbin/kvm_mkdb/kvm_mkdb.c        7 Nov 2015 13:36:41 -0000
@@ -98,9 +98,6 @@ main(int argc, char *argv[])
        if (argc > 1)
                usage();
 
-       if (pledge("stdio rpath wpath cpath fattr flock", NULL) == -1)
-               err(1, "pledge");
-
        /* If no kernel specified use _PATH_KSYMS and fall back to _PATH_UNIX */
        if (argc > 0) {
                nlistpath = argv[0];
@@ -171,6 +168,10 @@ kvm_mkdb(int fd, const char *dbdir, char
                (void)unlink(dbtemp);
                return(1);
        }
+
+       /* rename() later */
+       if (pledge("stdio rpath wpath cpath fattr flock", NULL) == -1)
+               err(1, "pledge");
 
        if (create_knlist(nlistpath, fd, db) != 0) {
                warn("cannot determine executable type of %s", nlistpath);

Reply via email to