path: root/net/bpfilter
diff options
authorEric W. Biederman <>2020-06-25 13:12:59 -0500
committerEric W. Biederman <>2020-07-04 09:35:29 -0500
commite2dc9bf3f5275ca372001541e5f26af572976e65 (patch)
treec5ac5d724d6a9cd37714615ec860a8b639d9d9fd /net/bpfilter
parent1199c6c3da5197e9924a906b9de71b8d0ac62a01 (diff)
umd: Transform fork_usermode_blob into fork_usermode_driver
Instead of loading a binary blob into a temporary file with shmem_kernel_file_setup load a binary blob into a temporary tmpfs filesystem. This means that the blob can be stored in an init section and discared, and it means the binary blob will have a filename so can be executed normally. The only tricky thing about this code is that in the helper function blob_to_mnt __fput_sync is used. That is because a file can not be executed if it is still open for write, and the ordinary delayed close for kernel threads does not happen soon enough, which causes the following exec to fail. The function umd_load_blob is not called with any locks so this should be safe. Executing the blob normally winds up correcting several problems with the user mode driver code discovered by Tetsuo Handa[1]. By passing an ordinary filename into the exec, it is no longer necessary to figure out how to turn a O_RDWR file descriptor into a properly referende counted O_EXEC file descriptor that forbids all writes. For path based LSMs there are no new special cases. [1] v1: v2: Link: Reviewed-by: Greg Kroah-Hartman <> Acked-by: Alexei Starovoitov <> Tested-by: Alexei Starovoitov <> Signed-off-by: "Eric W. Biederman" <>
Diffstat (limited to 'net/bpfilter')
1 files changed, 11 insertions, 3 deletions
diff --git a/net/bpfilter/bpfilter_kern.c b/net/bpfilter/bpfilter_kern.c
index c0f0990f30b6..28883b00609d 100644
--- a/net/bpfilter/bpfilter_kern.c
+++ b/net/bpfilter/bpfilter_kern.c
@@ -77,9 +77,7 @@ static int start_umh(void)
int err;
/* fork usermode process */
- err = fork_usermode_blob(&bpfilter_umh_start,
- &bpfilter_umh_end - &bpfilter_umh_start,
- &;
+ err = fork_usermode_driver(&;
if (err)
return err;
bpfilter_ops.stop = false;
@@ -98,6 +96,12 @@ static int __init load_umh(void)
int err;
+ err = umd_load_blob(&,
+ &bpfilter_umh_start,
+ &bpfilter_umh_end - &bpfilter_umh_start);
+ if (err)
+ return err;
if (!bpfilter_ops.stop) {
err = -EFAULT;
@@ -110,6 +114,8 @@ static int __init load_umh(void)
+ if (err)
+ umd_unload_blob(&;
return err;
@@ -122,6 +128,8 @@ static void __exit fini_umh(void)
bpfilter_ops.sockopt = NULL;
+ umd_unload_blob(&;