diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index 717426d592eb..2d894d3f1c60 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -416,3 +416,5 @@ 399 common io_pgetevents sys_io_pgetevents 424 common pidfd_send_signal sys_pidfd_send_signal 434 common pidfd_open sys_pidfd_open +436 common close_range sys_close_range +441 common epoll_pwait2 sys_epoll_pwait2 diff --git a/arch/arm64/configs/vendor/bengal-perf_defconfig b/arch/arm64/configs/vendor/bengal-perf_defconfig index 76d4e54b5bf5..82fd1608639c 100644 --- a/arch/arm64/configs/vendor/bengal-perf_defconfig +++ b/arch/arm64/configs/vendor/bengal-perf_defconfig @@ -122,6 +122,7 @@ CONFIG_XFRM_INTERFACE=y CONFIG_XFRM_MIGRATE=y CONFIG_XFRM_STATISTICS=y CONFIG_NET_KEY=y +CONFIG_XDP_SOCKETS=y CONFIG_INET=y CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y diff --git a/arch/arm64/configs/vendor/kona-perf_defconfig b/arch/arm64/configs/vendor/kona-perf_defconfig index 8fd2d31e836a..73b3bc3e7c48 100644 --- a/arch/arm64/configs/vendor/kona-perf_defconfig +++ b/arch/arm64/configs/vendor/kona-perf_defconfig @@ -122,6 +122,7 @@ CONFIG_XFRM_INTERFACE=y CONFIG_XFRM_MIGRATE=y CONFIG_XFRM_STATISTICS=y CONFIG_NET_KEY=y +CONFIG_XDP_SOCKETS=y CONFIG_INET=y CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y diff --git a/arch/arm64/configs/vendor/lito-perf_defconfig b/arch/arm64/configs/vendor/lito-perf_defconfig index f31caa54d3e3..0582f6eb39b7 100644 --- a/arch/arm64/configs/vendor/lito-perf_defconfig +++ b/arch/arm64/configs/vendor/lito-perf_defconfig @@ -120,6 +120,7 @@ CONFIG_XFRM_INTERFACE=y CONFIG_XFRM_MIGRATE=y CONFIG_XFRM_STATISTICS=y CONFIG_NET_KEY=y +CONFIG_XDP_SOCKETS=y CONFIG_INET=y CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index b4910b4e8704..b40712acf878 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -49,7 +49,7 @@ #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5) #define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800) -#define __NR_compat_syscalls 435 +#define __NR_compat_syscalls 442 #endif #define __ARCH_WANT_SYS_CLONE diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index d27ae610cf55..5196e7934cd3 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h @@ -823,6 +823,10 @@ __SYSCALL(__NR_rseq, sys_rseq) __SYSCALL(__NR_pidfd_send_signal, sys_pidfd_send_signal) #define __NR_pidfd_open 434 __SYSCALL(__NR_pidfd_open, sys_pidfd_open) +#define __NR_close_range 436 +__SYSCALL(__NR_close_range, sys_close_range) +#define __NR_epoll_pwait2 441 +__SYSCALL(__NR_epoll_pwait2, compat_sys_epoll_pwait2) /* * Please add new compat syscalls above this comment and update diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl index 8caf42ae102a..8f362f87d5e4 100644 --- a/arch/s390/kernel/syscalls/syscall.tbl +++ b/arch/s390/kernel/syscalls/syscall.tbl @@ -393,3 +393,5 @@ 383 common rseq sys_rseq compat_sys_rseq 424 common pidfd_send_signal sys_pidfd_send_signal sys_pidfd_send_signal 434 common pidfd_open sys_pidfd_open sys_pidfd_open +436 common close_range sys_close_range sys_close_range +441 common epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2 diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index bb3a1b34171e..f919d7243932 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -400,3 +400,5 @@ 386 i386 rseq sys_rseq __ia32_sys_rseq 424 i386 pidfd_send_signal sys_pidfd_send_signal __ia32_sys_pidfd_send_signal 434 i386 pidfd_open sys_pidfd_open __ia32_sys_pidfd_open +436 i386 close_range sys_close_range +441 i386 epoll_pwait2 sys_epoll_pwait2 __ia32_sys_epoll_pwait2 diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index af1ce3a1dea2..e66a990f2578 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -341,6 +341,8 @@ 332 common statx sys_statx 424 common pidfd_send_signal sys_pidfd_send_signal 434 common pidfd_open sys_pidfd_open +436 common close_range sys_close_range +441 common epoll_pwait2 sys_epoll_pwait2 # # x32-specific system call numbers start at 512 to avoid cache impact diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c index a27b96345f2f..3c28b55257d5 100644 --- a/drivers/bus/mhi/core/mhi_init.c +++ b/drivers/bus/mhi/core/mhi_init.c @@ -1572,8 +1572,7 @@ int of_register_mhi_controller(struct mhi_controller *mhi_cntrl) INIT_WORK(&mhi_cntrl->st_worker, mhi_pm_st_worker); init_waitqueue_head(&mhi_cntrl->state_event); - mhi_cntrl->wq = alloc_ordered_workqueue("mhi_w", - WQ_MEM_RECLAIM | WQ_HIGHPRI); + mhi_cntrl->wq = alloc_ordered_workqueue("mhi_w", WQ_HIGHPRI); if (!mhi_cntrl->wq) goto error_alloc_cmd; diff --git a/drivers/media/platform/msm/cvp/hfi_response_handler.c b/drivers/media/platform/msm/cvp/hfi_response_handler.c index 5447a9624000..405f906ee3a2 100644 --- a/drivers/media/platform/msm/cvp/hfi_response_handler.c +++ b/drivers/media/platform/msm/cvp/hfi_response_handler.c @@ -480,7 +480,7 @@ static int hfi_process_session_cvp_msg(u32 device_id, struct cvp_session_msg *sess_msg; struct msm_cvp_inst *inst = NULL; struct msm_cvp_core *core; - void *session_id; + unsigned int session_id; if (!pkt) { dprintk(CVP_ERR, "%s: invalid param\n", __func__); @@ -489,9 +489,9 @@ static int hfi_process_session_cvp_msg(u32 device_id, dprintk(CVP_ERR, "%s: bad_pkt_size %d\n", __func__, pkt->size); return -E2BIG; } - session_id = (void *)(uintptr_t)get_msg_session_id(pkt); + session_id = get_msg_session_id(pkt); core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list); - inst = cvp_get_inst_from_id(core, (unsigned int)session_id); + inst = cvp_get_inst_from_id(core, session_id); if (!inst) { dprintk(CVP_ERR, "%s: invalid session\n", __func__); diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c index 6dfdcffcd2ef..69ba33481f4b 100644 --- a/drivers/power/supply/qcom/qpnp-qg.c +++ b/drivers/power/supply/qcom/qpnp-qg.c @@ -4794,7 +4794,7 @@ static int qpnp_qg_probe(struct platform_device *pdev) chip->batt_age_level = -EINVAL; chip->qg_charge_counter = -EINVAL; - chip->qg_version = (u8)of_device_get_match_data(&pdev->dev); + chip->qg_version = (enum qg_version)of_device_get_match_data(&pdev->dev); switch (chip->qg_version) { case QG_LITE: diff --git a/drivers/power/supply/qcom/smb1390-charger-psy.c b/drivers/power/supply/qcom/smb1390-charger-psy.c index 7a4127e5a187..fcc6de58c203 100644 --- a/drivers/power/supply/qcom/smb1390-charger-psy.c +++ b/drivers/power/supply/qcom/smb1390-charger-psy.c @@ -2101,7 +2101,7 @@ static int smb1390_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, chip); - chip->cp_role = (int)of_device_get_match_data(chip->dev); + chip->cp_role = (int)(unsigned long)of_device_get_match_data(chip->dev); switch (chip->cp_role) { case CP_MASTER: rc = smb1390_master_probe(chip); diff --git a/drivers/power/supply/qcom/smb1398-charger.c b/drivers/power/supply/qcom/smb1398-charger.c index 513b49c0a31f..ec763cc31708 100644 --- a/drivers/power/supply/qcom/smb1398-charger.c +++ b/drivers/power/supply/qcom/smb1398-charger.c @@ -2732,7 +2732,7 @@ static int smb1398_probe(struct platform_device *pdev) chip->disabled = true; platform_set_drvdata(pdev, chip); - chip->div2_cp_role = (int)of_device_get_match_data(chip->dev); + chip->div2_cp_role = (int)(unsigned long)of_device_get_match_data(chip->dev); switch (chip->div2_cp_role) { case DIV2_CP_MASTER: case SMB1394_DIV2_CP_PRY: diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 9a81b5621c6c..f88304e05188 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1713,15 +1713,25 @@ static int ep_send_events(struct eventpoll *ep, return esed.res; } -static inline struct timespec64 ep_set_mstimeout(long ms) +static struct timespec64 *ep_timeout_to_timespec(struct timespec64 *to, long ms) { - struct timespec64 now, ts = { - .tv_sec = ms / MSEC_PER_SEC, - .tv_nsec = NSEC_PER_MSEC * (ms % MSEC_PER_SEC), - }; + struct timespec64 now; + + if (ms < 0) + return NULL; + + if (!ms) { + to->tv_sec = 0; + to->tv_nsec = 0; + return to; + } + + to->tv_sec = ms / MSEC_PER_SEC; + to->tv_nsec = NSEC_PER_MSEC * (ms % MSEC_PER_SEC); ktime_get_ts64(&now); - return timespec64_add_safe(now, ts); + *to = timespec64_add_safe(now, *to); + return to; } /** @@ -1733,8 +1743,8 @@ static inline struct timespec64 ep_set_mstimeout(long ms) * stored. * @maxevents: Size (in terms of number of events) of the caller event buffer. * @timeout: Maximum timeout for the ready events fetch operation, in - * milliseconds. If the @timeout is zero, the function will not block, - * while if the @timeout is less than zero, the function will block + * timespec. If the timeout is zero, the function will not block, + * while if the @timeout ptr is NULL, the function will block * until at least one event has been retrieved (or an error * occurred). * @@ -1742,7 +1752,7 @@ static inline struct timespec64 ep_set_mstimeout(long ms) * error code, in case of error. */ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, - int maxevents, long timeout) + int maxevents, struct timespec64 *timeout) { int res = 0, eavail, timed_out = 0; u64 slack = 0; @@ -1751,13 +1761,11 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, lockdep_assert_irqs_enabled(); - if (timeout > 0) { - struct timespec64 end_time = ep_set_mstimeout(timeout); - - slack = select_estimate_accuracy(&end_time); + if (timeout && (timeout->tv_sec | timeout->tv_nsec)) { + slack = select_estimate_accuracy(timeout); to = &expires; - *to = timespec64_to_ktime(end_time); - } else if (timeout == 0) { + *to = timespec64_to_ktime(*timeout); + } else if (timeout) { /* * Avoid the unnecessary trip to the wait queue loop, if the * caller specified a non blocking operation. @@ -2155,7 +2163,7 @@ error_return: * part of the user space epoll_wait(2). */ static int do_epoll_wait(int epfd, struct epoll_event __user *events, - int maxevents, int timeout) + int maxevents, struct timespec64 *to) { int error; struct fd f; @@ -2189,7 +2197,7 @@ static int do_epoll_wait(int epfd, struct epoll_event __user *events, ep = f.file->private_data; /* Time to fish for events ... */ - error = ep_poll(ep, events, maxevents, timeout); + error = ep_poll(ep, events, maxevents, to); error_fput: fdput(f); @@ -2199,16 +2207,19 @@ error_fput: SYSCALL_DEFINE4(epoll_wait, int, epfd, struct epoll_event __user *, events, int, maxevents, int, timeout) { - return do_epoll_wait(epfd, events, maxevents, timeout); + struct timespec64 to; + + return do_epoll_wait(epfd, events, maxevents, + ep_timeout_to_timespec(&to, timeout)); } /* * Implement the event wait interface for the eventpoll file. It is the kernel * part of the user space epoll_pwait(2). */ -SYSCALL_DEFINE6(epoll_pwait, int, epfd, struct epoll_event __user *, events, - int, maxevents, int, timeout, const sigset_t __user *, sigmask, - size_t, sigsetsize) +static int do_epoll_pwait(int epfd, struct epoll_event __user *events, + int maxevents, struct timespec64 *to, + const sigset_t __user *sigmask, size_t sigsetsize) { int error; sigset_t ksigmask, sigsaved; @@ -2226,7 +2237,7 @@ SYSCALL_DEFINE6(epoll_pwait, int, epfd, struct epoll_event __user *, events, set_current_blocked(&ksigmask); } - error = do_epoll_wait(epfd, events, maxevents, timeout); + error = do_epoll_wait(epfd, events, maxevents, to); /* * If we changed the signal mask, we need to restore the original one. @@ -2246,12 +2257,40 @@ SYSCALL_DEFINE6(epoll_pwait, int, epfd, struct epoll_event __user *, events, return error; } +SYSCALL_DEFINE6(epoll_pwait, int, epfd, struct epoll_event __user *, events, + int, maxevents, int, timeout, const sigset_t __user *, sigmask, + size_t, sigsetsize) +{ + struct timespec64 to; + + return do_epoll_pwait(epfd, events, maxevents, + ep_timeout_to_timespec(&to, timeout), + sigmask, sigsetsize); +} + +SYSCALL_DEFINE6(epoll_pwait2, int, epfd, struct epoll_event __user *, events, + int, maxevents, const struct __kernel_timespec __user *, timeout, + const sigset_t __user *, sigmask, size_t, sigsetsize) +{ + struct timespec64 ts, *to = NULL; + + if (timeout) { + if (get_timespec64(&ts, timeout)) + return -EFAULT; + to = &ts; + if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec)) + return -EINVAL; + } + + return do_epoll_pwait(epfd, events, maxevents, to, + sigmask, sigsetsize); +} + #ifdef CONFIG_COMPAT -COMPAT_SYSCALL_DEFINE6(epoll_pwait, int, epfd, - struct epoll_event __user *, events, - int, maxevents, int, timeout, - const compat_sigset_t __user *, sigmask, - compat_size_t, sigsetsize) +static int do_compat_epoll_pwait(int epfd, struct epoll_event __user *events, + int maxevents, struct timespec64 *timeout, + const compat_sigset_t __user *sigmask, + compat_size_t sigsetsize) { long err; sigset_t ksigmask, sigsaved; @@ -2288,6 +2327,41 @@ COMPAT_SYSCALL_DEFINE6(epoll_pwait, int, epfd, return err; } + +COMPAT_SYSCALL_DEFINE6(epoll_pwait, int, epfd, + struct epoll_event __user *, events, + int, maxevents, int, timeout, + const compat_sigset_t __user *, sigmask, + compat_size_t, sigsetsize) +{ + struct timespec64 to; + + return do_compat_epoll_pwait(epfd, events, maxevents, + ep_timeout_to_timespec(&to, timeout), + sigmask, sigsetsize); +} + +COMPAT_SYSCALL_DEFINE6(epoll_pwait2, int, epfd, + struct epoll_event __user *, events, + int, maxevents, + const struct __kernel_timespec __user *, timeout, + const compat_sigset_t __user *, sigmask, + compat_size_t, sigsetsize) +{ + struct timespec64 ts, *to = NULL; + + if (timeout) { + if (get_timespec64(&ts, timeout)) + return -EFAULT; + to = &ts; + if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec)) + return -EINVAL; + } + + return do_compat_epoll_pwait(epfd, events, maxevents, to, + sigmask, sigsetsize); +} + #endif static int __init eventpoll_init(void) diff --git a/fs/file.c b/fs/file.c index 8916578b6385..cc9b34ae5e8a 100644 --- a/fs/file.c +++ b/fs/file.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,7 @@ #include #include #include +#include unsigned int sysctl_nr_open __read_mostly = 1024*1024; unsigned int sysctl_nr_open_min = BITS_PER_LONG; @@ -84,6 +86,14 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt) * 'unsigned long' in some places, but simply because that is how the Linux * kernel bitmaps are defined to work: they are not "bits in an array of bytes", * they are very much "bits in an array of unsigned long". + * + * The ALIGN(nr, BITS_PER_LONG) here is for clarity: since we just multiplied + * by that "1024/sizeof(ptr)" before, we already know there are sufficient + * clear low bits. Clang seems to realize that, gcc ends up being confused. + * + * On a 128-bit machine, the ALIGN() would actually matter. In the meantime, + * let's consider it documentation (and maybe a test-case for gcc to improve + * its code generation ;) */ static struct fdtable *alloc_fdtable(unsigned int slots_wanted) { @@ -272,36 +282,45 @@ static inline void __clear_open_fd(unsigned int fd, struct fdtable *fdt) __clear_bit(fd / BITS_PER_LONG, fdt->full_fds_bits); } -static unsigned int count_open_files(struct fdtable *fdt) +/* + * Note that a sane fdtable size always has to be a multiple of + * BITS_PER_LONG, since we have bitmaps that are sized by this. + * + * punch_hole is optional - when close_range() is asked to unshare + * and close, we don't need to copy descriptors in that range, so + * a smaller cloned descriptor table might suffice if the last + * currently opened descriptor falls into that range. + */ +static unsigned int sane_fdtable_size(struct fdtable *fdt, struct fd_range *punch_hole) { - unsigned int size = fdt->max_fds; - unsigned int i; + unsigned int last = find_last_bit(fdt->open_fds, fdt->max_fds); - /* Find the last open fd */ - for (i = size / BITS_PER_LONG; i > 0; ) { - if (fdt->open_fds[--i]) - break; + if (last == fdt->max_fds) + return NR_OPEN_DEFAULT; + if (punch_hole && punch_hole->to >= last && punch_hole->from <= last) { + last = find_last_bit(fdt->open_fds, punch_hole->from); + if (last == punch_hole->from) + return NR_OPEN_DEFAULT; } - i = (i + 1) * BITS_PER_LONG; - return i; + return ALIGN(last + 1, BITS_PER_LONG); } /* - * Allocate a new files structure and copy contents from the - * passed in files structure. - * errorp will be valid only when the returned files_struct is NULL. + * Allocate a new descriptor table and copy contents from the passed in + * instance. Returns a pointer to cloned table on success, ERR_PTR() + * on failure. For 'punch_hole' see sane_fdtable_size(). */ -struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) +struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_hole) { struct files_struct *newf; struct file **old_fds, **new_fds; unsigned int open_files, i; struct fdtable *old_fdt, *new_fdt; + int error; - *errorp = -ENOMEM; newf = kmem_cache_alloc(files_cachep, GFP_KERNEL); if (!newf) - goto out; + return ERR_PTR(-ENOMEM); atomic_set(&newf->count, 1); @@ -318,7 +337,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) spin_lock(&oldf->file_lock); old_fdt = files_fdtable(oldf); - open_files = count_open_files(old_fdt); + open_files = sane_fdtable_size(old_fdt, punch_hole); /* * Check whether we need to allocate a larger fd array and fd set. @@ -331,7 +350,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) new_fdt = alloc_fdtable(open_files); if (IS_ERR(new_fdt)) { - *errorp = PTR_ERR(new_fdt); + error = PTR_ERR(new_fdt); goto out_release; } @@ -342,7 +361,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) */ spin_lock(&oldf->file_lock); old_fdt = files_fdtable(oldf); - open_files = count_open_files(old_fdt); + open_files = sane_fdtable_size(old_fdt, punch_hole); } copy_fd_bitmaps(new_fdt, old_fdt, open_files / BITS_PER_LONG); @@ -376,8 +395,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) out_release: kmem_cache_free(files_cachep, newf); -out: - return NULL; + return ERR_PTR(error); } static struct fdtable *close_files(struct files_struct * files) @@ -630,12 +648,9 @@ void fd_install(unsigned int fd, struct file *file) EXPORT_SYMBOL(fd_install); -/* - * The same warnings as for __alloc_fd()/__fd_install() apply here... - */ -int __close_fd(struct files_struct *files, unsigned fd) +static struct file *pick_file(struct files_struct *files, unsigned fd) { - struct file *file; + struct file *file = NULL; struct fdtable *fdt; spin_lock(&files->file_lock); @@ -648,15 +663,129 @@ int __close_fd(struct files_struct *files, unsigned fd) goto out_unlock; rcu_assign_pointer(fdt->fd[fd], NULL); __put_unused_fd(files, fd); - spin_unlock(&files->file_lock); - return filp_close(file, files); out_unlock: spin_unlock(&files->file_lock); - return -EBADF; + return file; +} + +/* + * The same warnings as for __alloc_fd()/__fd_install() apply here... + */ +int __close_fd(struct files_struct *files, unsigned fd) +{ + struct file *file; + + file = pick_file(files, fd); + if (!file) + return -EBADF; + + return filp_close(file, files); } EXPORT_SYMBOL(__close_fd); /* for ksys_close() */ +/** + * last_fd - return last valid index into fd table + * @cur_fds: files struct + * + * Context: Either rcu read lock or files_lock must be held. + * + * Returns: Last valid index into fdtable. + */ +static inline unsigned last_fd(struct fdtable *fdt) +{ + return fdt->max_fds - 1; +} + +static inline void __range_cloexec(struct files_struct *cur_fds, + unsigned int fd, unsigned int max_fd) +{ + struct fdtable *fdt; + + /* make sure we're using the correct maximum value */ + spin_lock(&cur_fds->file_lock); + fdt = files_fdtable(cur_fds); + max_fd = min(last_fd(fdt), max_fd); + if (fd <= max_fd) + bitmap_set(fdt->close_on_exec, fd, max_fd - fd + 1); + spin_unlock(&cur_fds->file_lock); +} + +static inline void __range_close(struct files_struct *cur_fds, unsigned int fd, + unsigned int max_fd) +{ + while (fd <= max_fd) { + struct file *file; + + file = pick_file(cur_fds, fd++); + if (!file) + continue; + + filp_close(file, cur_fds); + cond_resched(); + } +} + +/** + * __close_range() - Close all file descriptors in a given range. + * + * @fd: starting file descriptor to close + * @max_fd: last file descriptor to close + * + * This closes a range of file descriptors. All file descriptors + * from @fd up to and including @max_fd are closed. + */ +int __close_range(unsigned fd, unsigned max_fd, unsigned int flags) +{ + struct task_struct *me = current; + struct files_struct *cur_fds = me->files, *fds = NULL; + + if (flags & ~(CLOSE_RANGE_UNSHARE | CLOSE_RANGE_CLOEXEC)) + return -EINVAL; + + if (fd > max_fd) + return -EINVAL; + + if ((flags & CLOSE_RANGE_UNSHARE) && atomic_read(&cur_fds->count) > 1) { + struct fd_range range = {fd, max_fd}, *punch_hole = ⦥ + + /* + * If the caller requested all fds to be made cloexec we always + * copy all of the file descriptors since they still want to + * use them. + */ + if (flags & CLOSE_RANGE_CLOEXEC) + punch_hole = NULL; + + fds = dup_fd(cur_fds, punch_hole); + if (IS_ERR(fds)) + return PTR_ERR(fds); + /* + * We used to share our file descriptor table, and have now + * created a private one, make sure we're using it below. + */ + swap(cur_fds, fds); + } + + if (flags & CLOSE_RANGE_CLOEXEC) + __range_cloexec(cur_fds, fd, max_fd); + else + __range_close(cur_fds, fd, max_fd); + + if (fds) { + /* + * We're done closing the files we were supposed to. Time to install + * the new file descriptor table and drop the old one. + */ + task_lock(me); + me->files = cur_fds; + task_unlock(me); + put_files_struct(fds); + } + + return 0; +} + void do_close_on_exec(struct files_struct *files) { unsigned i; diff --git a/fs/open.c b/fs/open.c index accdc1b2ce9a..dbb91f0101bb 100644 --- a/fs/open.c +++ b/fs/open.c @@ -1213,6 +1213,23 @@ SYSCALL_DEFINE1(close, unsigned int, fd) return retval; } +/** + * close_range() - Close all file descriptors in a given range. + * + * @fd: starting file descriptor to close + * @max_fd: last file descriptor to close + * @flags: reserved for future extensions + * + * This closes a range of file descriptors. All file descriptors + * from @fd up to and including @max_fd are closed. + * Currently, errors to close a given file descriptor are ignored. + */ +SYSCALL_DEFINE3(close_range, unsigned int, fd, unsigned int, max_fd, + unsigned int, flags) +{ + return __close_range(fd, max_fd, flags); +} + /* * This routine simulates a hangup on the tty, to arrange that users * are given clean terminals at login time. diff --git a/include/linux/compat.h b/include/linux/compat.h index 654f7aae4bfe..0700afb33302 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -568,6 +568,12 @@ asmlinkage long compat_sys_epoll_pwait(int epfd, int maxevents, int timeout, const compat_sigset_t __user *sigmask, compat_size_t sigsetsize); +asmlinkage long compat_sys_epoll_pwait2(int epfd, + struct epoll_event __user *events, + int maxevents, + const struct __kernel_timespec __user *timeout, + const compat_sigset_t __user *sigmask, + compat_size_t sigsetsize); /* fs/fcntl.c */ asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd, diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h index 41615f38bcff..6662e2a91472 100644 --- a/include/linux/fdtable.h +++ b/include/linux/fdtable.h @@ -109,7 +109,10 @@ struct files_struct *get_files_struct(struct task_struct *); void put_files_struct(struct files_struct *fs); void reset_files_struct(struct files_struct *); int unshare_files(struct files_struct **); -struct files_struct *dup_fd(struct files_struct *, int *) __latent_entropy; +struct fd_range { + unsigned int from, to; +}; +struct files_struct *dup_fd(struct files_struct *, struct fd_range *) __latent_entropy; void do_close_on_exec(struct files_struct *); int iterate_fd(struct files_struct *, unsigned, int (*)(const void *, struct file *, unsigned), @@ -121,6 +124,7 @@ extern void __fd_install(struct files_struct *files, unsigned int fd, struct file *file); extern int __close_fd(struct files_struct *files, unsigned int fd); +extern int __close_range(unsigned int fd, unsigned int max_fd, unsigned int flags); extern struct kmem_cache *files_cachep; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 662c976882b8..a557a209d3d4 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -599,6 +599,9 @@ struct netdev_queue { /* Subordinate device that the queue has been assigned to */ struct net_device *sb_dev; +#ifdef CONFIG_XDP_SOCKETS + struct xdp_umem *umem; +#endif /* * write-mostly part */ @@ -736,6 +739,9 @@ struct netdev_rx_queue { struct kobject kobj; struct net_device *dev; struct xdp_rxq_info xdp_rxq; +#ifdef CONFIG_XDP_SOCKETS + struct xdp_umem *umem; +#endif ANDROID_KABI_RESERVE(1); ANDROID_KABI_RESERVE(2); diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 895ff567ab20..2f75f80f8ecf 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -346,6 +346,11 @@ asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events, int maxevents, int timeout, const sigset_t __user *sigmask, size_t sigsetsize); +asmlinkage long sys_epoll_pwait2(int epfd, struct epoll_event __user *events, + int maxevents, + const struct __kernel_timespec __user *timeout, + const sigset_t __user *sigmask, + size_t sigsetsize); /* fs/fcntl.c */ asmlinkage long sys_dup(unsigned int fildes); @@ -423,6 +428,8 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group); asmlinkage long sys_openat(int dfd, const char __user *filename, int flags, umode_t mode); asmlinkage long sys_close(unsigned int fd); +asmlinkage long sys_close_range(unsigned int fd, unsigned int max_fd, + unsigned int flags); asmlinkage long sys_vhangup(void); /* fs/pipe.c */ diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index be311b944b19..2c6b9e225737 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -740,9 +740,13 @@ __SYSCALL(__NR_rseq, sys_rseq) __SYSCALL(__NR_pidfd_send_signal, sys_pidfd_send_signal) #define __NR_pidfd_open 434 __SYSCALL(__NR_pidfd_open, sys_pidfd_open) +#define __NR_close_range 436 +__SYSCALL(__NR_close_range, sys_close_range) +#define __NR_epoll_pwait2 441 +__SC_COMP(__NR_epoll_pwait2, sys_epoll_pwait2, compat_sys_epoll_pwait2) #undef __NR_syscalls -#define __NR_syscalls 435 +#define __NR_syscalls 442 /* * 32 bit systems traditionally used different diff --git a/include/uapi/linux/close_range.h b/include/uapi/linux/close_range.h new file mode 100644 index 000000000000..2d804281554c --- /dev/null +++ b/include/uapi/linux/close_range.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_LINUX_CLOSE_RANGE_H +#define _UAPI_LINUX_CLOSE_RANGE_H + +/* Unshare the file descriptor table before closing file descriptors. */ +#define CLOSE_RANGE_UNSHARE (1U << 1) + +/* Set the FD_CLOEXEC bit instead of closing the file descriptor. */ +#define CLOSE_RANGE_CLOEXEC (1U << 2) + +#endif /* _UAPI_LINUX_CLOSE_RANGE_H */ + diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 444cccb8fcd3..6719a1bb0028 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -6482,6 +6482,7 @@ void cgroup_sk_clone(struct sock_cgroup_data *skcd) * Don't use cgroup_get_live(). */ cgroup_get(sock_cgroup_ptr(skcd)); + cgroup_bpf_get(sock_cgroup_ptr(skcd)); } } diff --git a/kernel/fork.c b/kernel/fork.c index f15453d932f8..c980b12a8dd4 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1399,28 +1399,25 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk) static int copy_files(unsigned long clone_flags, struct task_struct *tsk) { struct files_struct *oldf, *newf; - int error = 0; /* * A background process may not have any files ... */ oldf = current->files; if (!oldf) - goto out; + return 0; if (clone_flags & CLONE_FILES) { atomic_inc(&oldf->count); - goto out; + return 0; } - newf = dup_fd(oldf, &error); - if (!newf) - goto out; + newf = dup_fd(oldf, NULL); + if (IS_ERR(newf)) + return PTR_ERR(newf); tsk->files = newf; - error = 0; -out: - return error; + return 0; } static int copy_io(unsigned long clone_flags, struct task_struct *tsk) @@ -2616,13 +2613,13 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp) static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp) { struct files_struct *fd = current->files; - int error = 0; if ((unshare_flags & CLONE_FILES) && (fd && atomic_read(&fd->count) > 1)) { - *new_fdp = dup_fd(fd, &error); - if (!*new_fdp) - return error; + fd = dup_fd(fd, NULL); + if (IS_ERR(fd)) + return PTR_ERR(fd); + *new_fdp = fd; } return 0; diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 7746849224e3..fd4e84d595a3 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -63,6 +63,8 @@ COND_SYSCALL(epoll_create1); COND_SYSCALL(epoll_ctl); COND_SYSCALL(epoll_pwait); COND_SYSCALL_COMPAT(epoll_pwait); +COND_SYSCALL(epoll_pwait2); +COND_SYSCALL_COMPAT(epoll_pwait2); /* fs/fcntl.c */ diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index aea780430d16..b8e796c8f6df 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn @@ -74,8 +74,6 @@ KBUILD_CFLAGS += $(call cc-disable-warning, uninitialized) KBUILD_CFLAGS += $(call cc-disable-warning, pointer-to-enum-cast) KBUILD_CFLAGS += $(call cc-disable-warning, unaligned-access) KBUILD_CFLAGS += $(call cc-disable-warning, cast-function-type-strict) -KBUILD_CFLAGS += $(call cc-disable-warning, pointer-to-int-cast) -KBUILD_CFLAGS += $(call cc-disable-warning, void-pointer-to-int-cast) KBUILD_CFLAGS += -Wno-enum-compare-conditional KBUILD_CFLAGS += -Wno-enum-enum-conversion endif diff --git a/techpack/display/msm/dp/dp_ctrl.c b/techpack/display/msm/dp/dp_ctrl.c index 88c419292c5a..564b4faa83ee 100644 --- a/techpack/display/msm/dp/dp_ctrl.c +++ b/techpack/display/msm/dp/dp_ctrl.c @@ -1342,7 +1342,7 @@ static void dp_ctrl_off(struct dp_ctrl *dp_ctrl) ctrl->catalog->fec_config(ctrl->catalog, false); dp_ctrl_configure_source_link_params(ctrl, false); - ctrl->catalog->reset(ctrl->catalog); + dp_ctrl_state_ctrl(ctrl, 0); /* Make sure DP is disabled before clk disable */ wmb(); diff --git a/techpack/display/msm/dsi/dsi_ctrl.c b/techpack/display/msm/dsi/dsi_ctrl.c index c92bfbcef14d..dca6467a9567 100644 --- a/techpack/display/msm/dsi/dsi_ctrl.c +++ b/techpack/display/msm/dsi/dsi_ctrl.c @@ -2715,6 +2715,7 @@ static irqreturn_t dsi_ctrl_isr(int irq, void *ptr) static int _dsi_ctrl_setup_isr(struct dsi_ctrl *dsi_ctrl) { int irq_num, rc; + uint32_t intr_idx; if (!dsi_ctrl) return -EINVAL; @@ -2726,6 +2727,22 @@ static int _dsi_ctrl_setup_isr(struct dsi_ctrl *dsi_ctrl) init_completion(&dsi_ctrl->irq_info.cmd_frame_done); init_completion(&dsi_ctrl->irq_info.bta_done); + /* If there is unbalanced refcount for any interrupt, irq_stat_mask + * does not get clear during suspend. On resume, enable irq is not + * called leading to ctrl ISR permanently disabled. This is a defensive + * check to recover from such scenario. + */ + for (intr_idx = DSI_SINT_CMD_MODE_DMA_DONE; + intr_idx < DSI_STATUS_INTERRUPT_COUNT; intr_idx++) { + if (dsi_ctrl->irq_info.irq_stat_refcount[intr_idx]) { + DSI_CTRL_ERR(dsi_ctrl, + "refcount mismatch: intr_idx %d\n", + intr_idx); + dsi_ctrl->irq_info.irq_stat_refcount[intr_idx] = 0; + } + } + dsi_ctrl->irq_info.irq_stat_mask = 0x0; + irq_num = platform_get_irq(dsi_ctrl->pdev, 0); if (irq_num < 0) { DSI_CTRL_ERR(dsi_ctrl, "Failed to get IRQ number, %d\n", @@ -2760,6 +2777,7 @@ static void _dsi_ctrl_destroy_isr(struct dsi_ctrl *dsi_ctrl) devm_free_irq(&dsi_ctrl->pdev->dev, dsi_ctrl->irq_info.irq_num, dsi_ctrl); dsi_ctrl->irq_info.irq_num = -1; + dsi_ctrl->irq_info.irq_stat_mask = 0x0; } } diff --git a/techpack/display/msm/sde/sde_encoder_phys_cmd.c b/techpack/display/msm/sde/sde_encoder_phys_cmd.c index 67ba03476d7f..4ed7b2c7058f 100644 --- a/techpack/display/msm/sde/sde_encoder_phys_cmd.c +++ b/techpack/display/msm/sde/sde_encoder_phys_cmd.c @@ -525,12 +525,14 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( pending_kickoff_cnt); SDE_EVT32(DRMID(phys_enc->parent), SDE_EVTLOG_FATAL); + mutex_lock(phys_enc->vblank_ctl_lock); sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_RDPTR); if (sde_kms_is_secure_session_inprogress(phys_enc->sde_kms)) SDE_DBG_DUMP("secure", "all", "dbg_bus"); else SDE_DBG_DUMP("all", "dbg_bus", "vbif_dbg_bus"); sde_encoder_helper_register_irq(phys_enc, INTR_IDX_RDPTR); + mutex_unlock(phys_enc->vblank_ctl_lock); } /* diff --git a/techpack/display/msm/sde/sde_kms.c b/techpack/display/msm/sde/sde_kms.c index fd91532fd91d..dfaa9a750de6 100644 --- a/techpack/display/msm/sde/sde_kms.c +++ b/techpack/display/msm/sde/sde_kms.c @@ -1278,7 +1278,7 @@ static void sde_kms_wait_for_commit_done(struct msm_kms *kms, sde_encoder_virt_reset(encoder); } - SDE_ATRACE_END("sde_ksm_wait_for_commit_done"); + SDE_ATRACE_END("sde_kms_wait_for_commit_done"); } static void sde_kms_prepare_fence(struct msm_kms *kms,