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);