Message ID | 20241204-udmabuf-fixes-v2-0-23887289de1c@google.com (mailing list archive) |
---|---|
Headers | show |
Series | fixes for udmabuf (memfd sealing checks and a leak) | expand |
Hi Jann, > Subject: [PATCH v2 0/3] fixes for udmabuf (memfd sealing checks and a leak) > > I have tested that patches 2 and 3 work using the following reproducers. > I did not write a reproducer for the issue described in patch 1. > > Reproducer for F_SEAL_FUTURE_WRITE not being respected: > ``` > #define _GNU_SOURCE > #include <err.h> > #include <fcntl.h> > #include <stdio.h> > #include <unistd.h> > #include <sys/ioctl.h> > #include <sys/mman.h> > #include <linux/udmabuf.h> > > #define SYSCHK(x) ({ \ > typeof(x) __res = (x); \ > if (__res == (typeof(x))-1) \ > err(1, "SYSCHK(" #x ")"); \ > __res; \ > }) > > int main(void) { > int memfd = SYSCHK(memfd_create("test", MFD_ALLOW_SEALING)); > SYSCHK(ftruncate(memfd, 0x1000)); > SYSCHK(fcntl(memfd, F_ADD_SEALS, > F_SEAL_SHRINK|F_SEAL_FUTURE_WRITE)); > int udmabuf_fd = SYSCHK(open("/dev/udmabuf", O_RDWR)); > struct udmabuf_create create_arg = { > .memfd = memfd, > .flags = 0, > .offset = 0, > .size = 0x1000 > }; > int buf_fd = SYSCHK(ioctl(udmabuf_fd, UDMABUF_CREATE, &create_arg)); > printf("created udmabuf buffer fd %d\n", buf_fd); > char *map = SYSCHK(mmap(NULL, 0x1000, PROT_READ|PROT_WRITE, > MAP_SHARED, buf_fd, 0)); > *map = 'a'; > } > ``` > > Reproducer for the memory leak (if you run this for a while, your memory > usage will steadily go up, and /sys/kernel/debug/dma_buf/bufinfo will > contain a ton of entries): > ``` > #define _GNU_SOURCE > #include <err.h> > #include <errno.h> > #include <assert.h> > #include <fcntl.h> > #include <stdio.h> > #include <unistd.h> > #include <sys/ioctl.h> > #include <sys/mman.h> > #include <sys/resource.h> > #include <linux/udmabuf.h> > > #define SYSCHK(x) ({ \ > typeof(x) __res = (x); \ > if (__res == (typeof(x))-1) \ > err(1, "SYSCHK(" #x ")"); \ > __res; \ > }) > > int main(void) { > int memfd = SYSCHK(memfd_create("test", MFD_ALLOW_SEALING)); > SYSCHK(ftruncate(memfd, 0x1000)); > SYSCHK(fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK)); > int udmabuf_fd = SYSCHK(open("/dev/udmabuf", O_RDWR)); > > // prevent creating new FDs > struct rlimit rlim = { .rlim_cur = 1, .rlim_max = 1 }; > SYSCHK(setrlimit(RLIMIT_NOFILE, &rlim)); > > while (1) { > struct udmabuf_create create_arg = { > .memfd = memfd, > .flags = 0, > .offset = 0, > .size = 0x1000 > }; > int buf_fd = ioctl(udmabuf_fd, UDMABUF_CREATE, &create_arg); > assert(buf_fd == -1); > assert(errno == EMFILE); > } > } > ``` > > Signed-off-by: Jann Horn <jannh@google.com> > --- > Changes in v2: > - patch 1/3: use file_inode instead of ->f_inode (Vivek) > - patch 1/3: add comment explaining the inode_lock_shared() > - patch 3/3: remove unused parameter (Vivek) > - patch 3/3: add comment on cleanup (Vivek) > - collect Acks > - Link to v1: https://lore.kernel.org/r/20241203-udmabuf-fixes-v1-0- > f99281c345aa@google.com > > --- > Jann Horn (3): > udmabuf: fix racy memfd sealing check > udmabuf: also check for F_SEAL_FUTURE_WRITE > udmabuf: fix memory leak on last export_udmabuf() error path Thank you for the fixes; all patches pushed to drm-misc-fixes. Thanks, Vivek > > drivers/dma-buf/udmabuf.c | 43 +++++++++++++++++++++++++++------------- > --- > 1 file changed, 27 insertions(+), 16 deletions(-) > --- > base-commit: b86545e02e8c22fb89218f29d381fa8e8b91d815 > change-id: 20241203-udmabuf-fixes-d0435ebab663 > > -- > Jann Horn <jannh@google.com>
I have tested that patches 2 and 3 work using the following reproducers. I did not write a reproducer for the issue described in patch 1. Reproducer for F_SEAL_FUTURE_WRITE not being respected: ``` #define _GNU_SOURCE #include <err.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <linux/udmabuf.h> #define SYSCHK(x) ({ \ typeof(x) __res = (x); \ if (__res == (typeof(x))-1) \ err(1, "SYSCHK(" #x ")"); \ __res; \ }) int main(void) { int memfd = SYSCHK(memfd_create("test", MFD_ALLOW_SEALING)); SYSCHK(ftruncate(memfd, 0x1000)); SYSCHK(fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK|F_SEAL_FUTURE_WRITE)); int udmabuf_fd = SYSCHK(open("/dev/udmabuf", O_RDWR)); struct udmabuf_create create_arg = { .memfd = memfd, .flags = 0, .offset = 0, .size = 0x1000 }; int buf_fd = SYSCHK(ioctl(udmabuf_fd, UDMABUF_CREATE, &create_arg)); printf("created udmabuf buffer fd %d\n", buf_fd); char *map = SYSCHK(mmap(NULL, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED, buf_fd, 0)); *map = 'a'; } ``` Reproducer for the memory leak (if you run this for a while, your memory usage will steadily go up, and /sys/kernel/debug/dma_buf/bufinfo will contain a ton of entries): ``` #define _GNU_SOURCE #include <err.h> #include <errno.h> #include <assert.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/resource.h> #include <linux/udmabuf.h> #define SYSCHK(x) ({ \ typeof(x) __res = (x); \ if (__res == (typeof(x))-1) \ err(1, "SYSCHK(" #x ")"); \ __res; \ }) int main(void) { int memfd = SYSCHK(memfd_create("test", MFD_ALLOW_SEALING)); SYSCHK(ftruncate(memfd, 0x1000)); SYSCHK(fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK)); int udmabuf_fd = SYSCHK(open("/dev/udmabuf", O_RDWR)); // prevent creating new FDs struct rlimit rlim = { .rlim_cur = 1, .rlim_max = 1 }; SYSCHK(setrlimit(RLIMIT_NOFILE, &rlim)); while (1) { struct udmabuf_create create_arg = { .memfd = memfd, .flags = 0, .offset = 0, .size = 0x1000 }; int buf_fd = ioctl(udmabuf_fd, UDMABUF_CREATE, &create_arg); assert(buf_fd == -1); assert(errno == EMFILE); } } ``` Signed-off-by: Jann Horn <jannh@google.com> --- Changes in v2: - patch 1/3: use file_inode instead of ->f_inode (Vivek) - patch 1/3: add comment explaining the inode_lock_shared() - patch 3/3: remove unused parameter (Vivek) - patch 3/3: add comment on cleanup (Vivek) - collect Acks - Link to v1: https://lore.kernel.org/r/20241203-udmabuf-fixes-v1-0-f99281c345aa@google.com --- Jann Horn (3): udmabuf: fix racy memfd sealing check udmabuf: also check for F_SEAL_FUTURE_WRITE udmabuf: fix memory leak on last export_udmabuf() error path drivers/dma-buf/udmabuf.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) --- base-commit: b86545e02e8c22fb89218f29d381fa8e8b91d815 change-id: 20241203-udmabuf-fixes-d0435ebab663