Message ID | 20200110213433.94739-3-minchan@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | introduce memory hinting API for external process | expand |
On 11.01.2020 00:34, Minchan Kim wrote: > There are usecases that System Management Software(SMS) want to give > a memory hint to other processes because it's not known to the > application. In the case of Android, ActivityManagerService daemon > manges app's life cycle and that daemon must be able to initiate > reclaim on its own without any app involvement. > > To solve the issue, this patch introduces new syscall process_madvise(2). > It uses pidfd of an external processs to give the hint. > > int process_madvise(int pidfd, void *addr, size_t length, int advise, > unsigned long flag); > > Since it could affect other process's address range, only privileged > process(CAP_SYS_PTRACE) or something else(e.g., being the same UID) > gives it the right to ptrace the process could use it successfully. > The flag argument is reserved for future use if we need to extend the > API. > > Supporting all hints madvise has/will supported/support to process_madvise > is rather risky. Because we are not sure all hints make sense from external > process and implementation for the hint may rely on the caller being > in the current context so it could be error-prone. Thus, I just limited > hints as MADV_[COLD|PAGEOUT] in this patch. > > If someone want to add other hints, we could hear hear the usecase and > review it for each hint. It's more safe for maintainace rather than > introducing a buggy syscall but hard to fix it later. > > Signed-off-by: Minchan Kim <minchan@kernel.org> > --- > arch/alpha/kernel/syscalls/syscall.tbl | 1 + > arch/arm/tools/syscall.tbl | 1 + > arch/arm64/include/asm/unistd.h | 2 +- > arch/arm64/include/asm/unistd32.h | 2 + > arch/ia64/kernel/syscalls/syscall.tbl | 1 + > arch/m68k/kernel/syscalls/syscall.tbl | 1 + > arch/microblaze/kernel/syscalls/syscall.tbl | 1 + > arch/mips/kernel/syscalls/syscall_n32.tbl | 1 + > arch/mips/kernel/syscalls/syscall_n64.tbl | 1 + > arch/parisc/kernel/syscalls/syscall.tbl | 1 + > arch/powerpc/kernel/syscalls/syscall.tbl | 1 + > arch/s390/kernel/syscalls/syscall.tbl | 1 + > arch/sh/kernel/syscalls/syscall.tbl | 1 + > arch/sparc/kernel/syscalls/syscall.tbl | 1 + > arch/x86/entry/syscalls/syscall_32.tbl | 1 + > arch/x86/entry/syscalls/syscall_64.tbl | 1 + > arch/xtensa/kernel/syscalls/syscall.tbl | 1 + > include/linux/syscalls.h | 2 + > include/uapi/asm-generic/unistd.h | 5 +- > kernel/sys_ni.c | 1 + > mm/madvise.c | 64 +++++++++++++++++++++ > 21 files changed, 89 insertions(+), 2 deletions(-) > > diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl > index e56950f23b49..776c61803315 100644 > --- a/arch/alpha/kernel/syscalls/syscall.tbl > +++ b/arch/alpha/kernel/syscalls/syscall.tbl > @@ -477,3 +477,4 @@ > # 545 reserved for clone3 > 546 common watch_devices sys_watch_devices > 547 common openat2 sys_openat2 > +548 common process_madvise sys_process_madvise > diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl > index 7fb2f4d59210..a43381542276 100644 > --- a/arch/arm/tools/syscall.tbl > +++ b/arch/arm/tools/syscall.tbl > @@ -451,3 +451,4 @@ > 435 common clone3 sys_clone3 > 436 common watch_devices sys_watch_devices > 437 common openat2 sys_openat2 > +438 common process_madvise sys_process_madvise > diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h > index 8aa00ccb0b96..b722e47377a5 100644 > --- a/arch/arm64/include/asm/unistd.h > +++ b/arch/arm64/include/asm/unistd.h > @@ -38,7 +38,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 438 > +#define __NR_compat_syscalls 439 > #endif > > #define __ARCH_WANT_SYS_CLONE > diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h > index 31f0ce25719e..5c82557d408f 100644 > --- a/arch/arm64/include/asm/unistd32.h > +++ b/arch/arm64/include/asm/unistd32.h > @@ -883,6 +883,8 @@ __SYSCALL(__NR_clone3, sys_clone3) > __SYSCALL(__NR_watch_devices, sys_watch_devices) > #define __NR_openat2 437 > __SYSCALL(__NR_openat2, sys_openat2) > +#define __NR_openat2 438 > +__SYSCALL(__NR_process_madvise, process_madvise) > > /* > * Please add new compat syscalls above this comment and update > diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl > index b9aa59931905..c156abc9a298 100644 > --- a/arch/ia64/kernel/syscalls/syscall.tbl > +++ b/arch/ia64/kernel/syscalls/syscall.tbl > @@ -358,3 +358,4 @@ > # 435 reserved for clone3 > 436 common watch_devices sys_watch_devices > 437 common openat2 sys_openat2 > +438 common process_madvise sys_process_madvise > diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl > index 868c1ef89d35..5b6034b6650f 100644 > --- a/arch/m68k/kernel/syscalls/syscall.tbl > +++ b/arch/m68k/kernel/syscalls/syscall.tbl > @@ -437,3 +437,4 @@ > # 435 reserved for clone3 > 436 common watch_devices sys_watch_devices > 437 common openat2 sys_openat2 > +438 common process_madvise sys_process_madvise > diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl > index 544b4cef18b3..4bef584af09c 100644 > --- a/arch/microblaze/kernel/syscalls/syscall.tbl > +++ b/arch/microblaze/kernel/syscalls/syscall.tbl > @@ -443,3 +443,4 @@ > 435 common clone3 sys_clone3 > 436 common watch_devices sys_watch_devices > 437 common openat2 sys_openat2 > +438 common process_madvise sys_process_madvise > diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl > index 05e8aee5dae7..94fbd0fcccce 100644 > --- a/arch/mips/kernel/syscalls/syscall_n32.tbl > +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl > @@ -376,3 +376,4 @@ > 435 n32 clone3 __sys_clone3 > 436 n32 watch_devices sys_watch_devices > 437 n32 openat2 sys_openat2 > +437 n32 process_madivse sys_process_madvise 438. And several places below has the same mistake. > diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl > index 24d6c01328fb..4e6982c429d5 100644 > --- a/arch/mips/kernel/syscalls/syscall_n64.tbl > +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl > @@ -352,3 +352,4 @@ > 435 n64 clone3 __sys_clone3 > 436 n64 watch_devices sys_watch_devices > 437 n64 openat2 sys_openat2 > +437 n64 process_madvise sys_process_madvise > diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl > index 4b5f77a4e1a2..3aa990caf9dc 100644 > --- a/arch/parisc/kernel/syscalls/syscall.tbl > +++ b/arch/parisc/kernel/syscalls/syscall.tbl > @@ -435,3 +435,4 @@ > 435 common clone3 sys_clone3_wrapper > 436 common watch_devices sys_watch_devices > 437 common openat2 sys_openat2 > +437 common process_madvise sys_process_madvise > diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl > index 9716dc85a517..30e727a23f33 100644 > --- a/arch/powerpc/kernel/syscalls/syscall.tbl > +++ b/arch/powerpc/kernel/syscalls/syscall.tbl > @@ -519,3 +519,4 @@ > 435 nospu clone3 ppc_clone3 > 436 common watch_devices sys_watch_devices > 437 common openat2 sys_openat2 > +437 common process_madvise sys_process_madvise > diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl > index 7da330f8b03e..75722e5ff496 100644 > --- a/arch/s390/kernel/syscalls/syscall.tbl > +++ b/arch/s390/kernel/syscalls/syscall.tbl > @@ -440,3 +440,4 @@ > 435 common clone3 sys_clone3 sys_clone3 > 436 common watch_devices sys_watch_devices sys_watch_devices > 437 common openat2 sys_openat2 sys_openat2 > +437 common process_madvise sys_process_madvise sys_process_madvise > diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl > index bb7e68e25337..7d7bc7befad3 100644 > --- a/arch/sh/kernel/syscalls/syscall.tbl > +++ b/arch/sh/kernel/syscalls/syscall.tbl > @@ -440,3 +440,4 @@ > # 435 reserved for clone3 > 436 common watch_devices sys_watch_devices > 437 common openat2 sys_openat2 > +437 common process_madvise sys_process_madvise > diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl > index 646a1fad7218..581d331ff62f 100644 > --- a/arch/sparc/kernel/syscalls/syscall.tbl > +++ b/arch/sparc/kernel/syscalls/syscall.tbl > @@ -483,3 +483,4 @@ > # 435 reserved for clone3 > 436 common watch_devices sys_watch_devices > 437 common openat2 sys_openat2 > +437 common process_madvise sys_process_madvise > diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl > index 57c53acee290..76a2c266fe7e 100644 > --- a/arch/x86/entry/syscalls/syscall_32.tbl > +++ b/arch/x86/entry/syscalls/syscall_32.tbl > @@ -442,3 +442,4 @@ > 435 i386 clone3 sys_clone3 __ia32_sys_clone3 > 436 i386 watch_devices sys_watch_devices __ia32_sys_watch_devices > 437 i386 openat2 sys_openat2 __ia32_sys_openat2 > +438 i386 process_madvise sys_process_madvise __ia32_sys_process_madvise > diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl > index 1dd8d21f6500..b697cd8620cb 100644 > --- a/arch/x86/entry/syscalls/syscall_64.tbl > +++ b/arch/x86/entry/syscalls/syscall_64.tbl > @@ -359,6 +359,7 @@ > 435 common clone3 __x64_sys_clone3/ptregs > 436 common watch_devices __x64_sys_watch_devices > 437 common openat2 __x64_sys_openat2 > +438 common process_madvise __x64_sys_process_madvise > > # > # x32-specific system call numbers start at 512 to avoid cache impact > diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl > index 0f48ab7bd75b..2e9813ecfd7d 100644 > --- a/arch/xtensa/kernel/syscalls/syscall.tbl > +++ b/arch/xtensa/kernel/syscalls/syscall.tbl > @@ -408,3 +408,4 @@ > 435 common clone3 sys_clone3 > 436 common watch_devices sys_watch_devices > 437 common openat2 sys_openat2 > +438 common process_madvise sys_process_madvise > diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h > index 433c8c85636e..1b58a11ff49f 100644 > --- a/include/linux/syscalls.h > +++ b/include/linux/syscalls.h > @@ -877,6 +877,8 @@ asmlinkage long sys_munlockall(void); > asmlinkage long sys_mincore(unsigned long start, size_t len, > unsigned char __user * vec); > asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior); > +asmlinkage long sys_process_madvise(int pidfd, unsigned long start, > + size_t len, int behavior, unsigned long flags); > asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, > unsigned long prot, unsigned long pgoff, > unsigned long flags); > diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h > index 33f3856a9c3c..4bcd8d366f38 100644 > --- a/include/uapi/asm-generic/unistd.h > +++ b/include/uapi/asm-generic/unistd.h > @@ -856,8 +856,11 @@ __SYSCALL(__NR_watch_devices, sys_watch_devices) > #define __NR_openat2 437 > __SYSCALL(__NR_openat2, sys_openat2) > > +#define __NR_openat2 438 > +__SYSCALL(__NR_process_madvise, sys_process_madvise) > + > #undef __NR_syscalls > -#define __NR_syscalls 438 > +#define __NR_syscalls 439 > > /* > * 32 bit systems traditionally used different > diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c > index 0e9b275260f8..10ce5eac8b4b 100644 > --- a/kernel/sys_ni.c > +++ b/kernel/sys_ni.c > @@ -281,6 +281,7 @@ COND_SYSCALL(mlockall); > COND_SYSCALL(munlockall); > COND_SYSCALL(mincore); > COND_SYSCALL(madvise); > +COND_SYSCALL(process_madvise); > COND_SYSCALL(remap_file_pages); > COND_SYSCALL(mbind); > COND_SYSCALL_COMPAT(mbind); > diff --git a/mm/madvise.c b/mm/madvise.c > index 0c901de531e4..e15dfb4df7bf 100644 > --- a/mm/madvise.c > +++ b/mm/madvise.c > @@ -17,6 +17,7 @@ > #include <linux/falloc.h> > #include <linux/fadvise.h> > #include <linux/sched.h> > +#include <linux/sched/mm.h> > #include <linux/ksm.h> > #include <linux/fs.h> > #include <linux/file.h> > @@ -993,6 +994,18 @@ madvise_behavior_valid(int behavior) > } > } > > +static bool > +process_madvise_behavior_valid(int behavior) > +{ > + switch (behavior) { > + case MADV_COLD: > + case MADV_PAGEOUT: > + return true; > + default: > + return false; > + } > +} > + > /* > * madvise_common - request behavior hint to address range of the target process > * > @@ -1169,3 +1182,54 @@ SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior) > { > return madvise_common(current, current->mm, start, len_in, behavior); > } > + > +SYSCALL_DEFINE5(process_madvise, int, pidfd, unsigned long, start, > + size_t, len_in, int, behavior, unsigned long, flags) I don't like the interface. The fact we have pidfd does not mean, we have to use it for new syscalls always. A user may want to set madvise for specific pid from console and pass pid as argument. pidfd would be an overkill in this case. We usually call "kill -9 pid" from console. Why shouldn't process_madvise() allow this? I suggent to extend first argument to work with both pid and pidfd. Look at what we have for waitid(idtype, id_t id, ...) for example: idtype == P_PID Wait for the child whose process ID matches id. idtype == P_PIDFD (since Linux 5.4) Wait for the child referred to by the PID file descriptor specified in id. (See pidfd_open(2) for further information on PID file descriptors.) We may use @flags argument for this. > +{ > + int ret; > + struct fd f; > + struct pid *pid; > + struct task_struct *task; > + struct mm_struct *mm; > + > + if (flags != 0) > + return -EINVAL; > + > + if (!process_madvise_behavior_valid(behavior)) > + return -EINVAL; > + > + f = fdget(pidfd); > + if (!f.file) > + return -EBADF; > + > + pid = pidfd_pid(f.file); > + if (IS_ERR(pid)) { > + ret = PTR_ERR(pid); > + goto err; > + } From here: > + rcu_read_lock(); > + task = pid_task(pid, PIDTYPE_PID); > + if (!task) { > + rcu_read_unlock(); > + ret = -ESRCH; > + goto err; > + } > + > + get_task_struct(task); > + rcu_read_unlock(); to here your code is a copy of existing get_pid_task(). We should the primitive instead. > + > + mm = mm_access(task, PTRACE_MODE_ATTACH_FSCREDS); > + if (IS_ERR_OR_NULL(mm)) { > + ret = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH; > + goto release_task; > + } > + > + ret = madvise_common(task, mm, start, len_in, behavior); > + mmput(mm); > +release_task: > + put_task_struct(task); > +err: Maybe s/err:/fdput:/ for uniformity with the above "release_task:"? > + fdput(f); > + return ret; > +} >
On Mon, Jan 13, 2020 at 11:47:11AM +0300, Kirill Tkhai wrote: > On 11.01.2020 00:34, Minchan Kim wrote: > > There are usecases that System Management Software(SMS) want to give > > a memory hint to other processes because it's not known to the > > application. In the case of Android, ActivityManagerService daemon > > manges app's life cycle and that daemon must be able to initiate > > reclaim on its own without any app involvement. > > > > To solve the issue, this patch introduces new syscall process_madvise(2). > > It uses pidfd of an external processs to give the hint. > > > > int process_madvise(int pidfd, void *addr, size_t length, int advise, > > unsigned long flag); > > > > Since it could affect other process's address range, only privileged > > process(CAP_SYS_PTRACE) or something else(e.g., being the same UID) > > gives it the right to ptrace the process could use it successfully. > > The flag argument is reserved for future use if we need to extend the > > API. > > > > Supporting all hints madvise has/will supported/support to process_madvise > > is rather risky. Because we are not sure all hints make sense from external > > process and implementation for the hint may rely on the caller being > > in the current context so it could be error-prone. Thus, I just limited > > hints as MADV_[COLD|PAGEOUT] in this patch. > > > > If someone want to add other hints, we could hear hear the usecase and > > review it for each hint. It's more safe for maintainace rather than > > introducing a buggy syscall but hard to fix it later. > > > > Signed-off-by: Minchan Kim <minchan@kernel.org> > > --- > > arch/alpha/kernel/syscalls/syscall.tbl | 1 + > > arch/arm/tools/syscall.tbl | 1 + > > arch/arm64/include/asm/unistd.h | 2 +- > > arch/arm64/include/asm/unistd32.h | 2 + > > arch/ia64/kernel/syscalls/syscall.tbl | 1 + > > arch/m68k/kernel/syscalls/syscall.tbl | 1 + > > arch/microblaze/kernel/syscalls/syscall.tbl | 1 + > > arch/mips/kernel/syscalls/syscall_n32.tbl | 1 + > > arch/mips/kernel/syscalls/syscall_n64.tbl | 1 + > > arch/parisc/kernel/syscalls/syscall.tbl | 1 + > > arch/powerpc/kernel/syscalls/syscall.tbl | 1 + > > arch/s390/kernel/syscalls/syscall.tbl | 1 + > > arch/sh/kernel/syscalls/syscall.tbl | 1 + > > arch/sparc/kernel/syscalls/syscall.tbl | 1 + > > arch/x86/entry/syscalls/syscall_32.tbl | 1 + > > arch/x86/entry/syscalls/syscall_64.tbl | 1 + > > arch/xtensa/kernel/syscalls/syscall.tbl | 1 + > > include/linux/syscalls.h | 2 + > > include/uapi/asm-generic/unistd.h | 5 +- > > kernel/sys_ni.c | 1 + > > mm/madvise.c | 64 +++++++++++++++++++++ > > 21 files changed, 89 insertions(+), 2 deletions(-) > > > > diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl > > index e56950f23b49..776c61803315 100644 > > --- a/arch/alpha/kernel/syscalls/syscall.tbl > > +++ b/arch/alpha/kernel/syscalls/syscall.tbl > > @@ -477,3 +477,4 @@ > > # 545 reserved for clone3 > > 546 common watch_devices sys_watch_devices > > 547 common openat2 sys_openat2 > > +548 common process_madvise sys_process_madvise > > diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl > > index 7fb2f4d59210..a43381542276 100644 > > --- a/arch/arm/tools/syscall.tbl > > +++ b/arch/arm/tools/syscall.tbl > > @@ -451,3 +451,4 @@ > > 435 common clone3 sys_clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +438 common process_madvise sys_process_madvise > > diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h > > index 8aa00ccb0b96..b722e47377a5 100644 > > --- a/arch/arm64/include/asm/unistd.h > > +++ b/arch/arm64/include/asm/unistd.h > > @@ -38,7 +38,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 438 > > +#define __NR_compat_syscalls 439 > > #endif > > > > #define __ARCH_WANT_SYS_CLONE > > diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h > > index 31f0ce25719e..5c82557d408f 100644 > > --- a/arch/arm64/include/asm/unistd32.h > > +++ b/arch/arm64/include/asm/unistd32.h > > @@ -883,6 +883,8 @@ __SYSCALL(__NR_clone3, sys_clone3) > > __SYSCALL(__NR_watch_devices, sys_watch_devices) > > #define __NR_openat2 437 > > __SYSCALL(__NR_openat2, sys_openat2) > > +#define __NR_openat2 438 > > +__SYSCALL(__NR_process_madvise, process_madvise) > > > > /* > > * Please add new compat syscalls above this comment and update > > diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl > > index b9aa59931905..c156abc9a298 100644 > > --- a/arch/ia64/kernel/syscalls/syscall.tbl > > +++ b/arch/ia64/kernel/syscalls/syscall.tbl > > @@ -358,3 +358,4 @@ > > # 435 reserved for clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +438 common process_madvise sys_process_madvise > > diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl > > index 868c1ef89d35..5b6034b6650f 100644 > > --- a/arch/m68k/kernel/syscalls/syscall.tbl > > +++ b/arch/m68k/kernel/syscalls/syscall.tbl > > @@ -437,3 +437,4 @@ > > # 435 reserved for clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +438 common process_madvise sys_process_madvise > > diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl > > index 544b4cef18b3..4bef584af09c 100644 > > --- a/arch/microblaze/kernel/syscalls/syscall.tbl > > +++ b/arch/microblaze/kernel/syscalls/syscall.tbl > > @@ -443,3 +443,4 @@ > > 435 common clone3 sys_clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +438 common process_madvise sys_process_madvise > > diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl > > index 05e8aee5dae7..94fbd0fcccce 100644 > > --- a/arch/mips/kernel/syscalls/syscall_n32.tbl > > +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl > > @@ -376,3 +376,4 @@ > > 435 n32 clone3 __sys_clone3 > > 436 n32 watch_devices sys_watch_devices > > 437 n32 openat2 sys_openat2 > > +437 n32 process_madivse sys_process_madvise > > 438. And several places below has the same mistake. > > > diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl > > index 24d6c01328fb..4e6982c429d5 100644 > > --- a/arch/mips/kernel/syscalls/syscall_n64.tbl > > +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl > > @@ -352,3 +352,4 @@ > > 435 n64 clone3 __sys_clone3 > > 436 n64 watch_devices sys_watch_devices > > 437 n64 openat2 sys_openat2 > > +437 n64 process_madvise sys_process_madvise > > diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl > > index 4b5f77a4e1a2..3aa990caf9dc 100644 > > --- a/arch/parisc/kernel/syscalls/syscall.tbl > > +++ b/arch/parisc/kernel/syscalls/syscall.tbl > > @@ -435,3 +435,4 @@ > > 435 common clone3 sys_clone3_wrapper > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +437 common process_madvise sys_process_madvise > > diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl > > index 9716dc85a517..30e727a23f33 100644 > > --- a/arch/powerpc/kernel/syscalls/syscall.tbl > > +++ b/arch/powerpc/kernel/syscalls/syscall.tbl > > @@ -519,3 +519,4 @@ > > 435 nospu clone3 ppc_clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +437 common process_madvise sys_process_madvise > > diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl > > index 7da330f8b03e..75722e5ff496 100644 > > --- a/arch/s390/kernel/syscalls/syscall.tbl > > +++ b/arch/s390/kernel/syscalls/syscall.tbl > > @@ -440,3 +440,4 @@ > > 435 common clone3 sys_clone3 sys_clone3 > > 436 common watch_devices sys_watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 sys_openat2 > > +437 common process_madvise sys_process_madvise sys_process_madvise > > diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl > > index bb7e68e25337..7d7bc7befad3 100644 > > --- a/arch/sh/kernel/syscalls/syscall.tbl > > +++ b/arch/sh/kernel/syscalls/syscall.tbl > > @@ -440,3 +440,4 @@ > > # 435 reserved for clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +437 common process_madvise sys_process_madvise > > diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl > > index 646a1fad7218..581d331ff62f 100644 > > --- a/arch/sparc/kernel/syscalls/syscall.tbl > > +++ b/arch/sparc/kernel/syscalls/syscall.tbl > > @@ -483,3 +483,4 @@ > > # 435 reserved for clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +437 common process_madvise sys_process_madvise > > diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl > > index 57c53acee290..76a2c266fe7e 100644 > > --- a/arch/x86/entry/syscalls/syscall_32.tbl > > +++ b/arch/x86/entry/syscalls/syscall_32.tbl > > @@ -442,3 +442,4 @@ > > 435 i386 clone3 sys_clone3 __ia32_sys_clone3 > > 436 i386 watch_devices sys_watch_devices __ia32_sys_watch_devices > > 437 i386 openat2 sys_openat2 __ia32_sys_openat2 > > +438 i386 process_madvise sys_process_madvise __ia32_sys_process_madvise > > diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl > > index 1dd8d21f6500..b697cd8620cb 100644 > > --- a/arch/x86/entry/syscalls/syscall_64.tbl > > +++ b/arch/x86/entry/syscalls/syscall_64.tbl > > @@ -359,6 +359,7 @@ > > 435 common clone3 __x64_sys_clone3/ptregs > > 436 common watch_devices __x64_sys_watch_devices > > 437 common openat2 __x64_sys_openat2 > > +438 common process_madvise __x64_sys_process_madvise > > > > # > > # x32-specific system call numbers start at 512 to avoid cache impact > > diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl > > index 0f48ab7bd75b..2e9813ecfd7d 100644 > > --- a/arch/xtensa/kernel/syscalls/syscall.tbl > > +++ b/arch/xtensa/kernel/syscalls/syscall.tbl > > @@ -408,3 +408,4 @@ > > 435 common clone3 sys_clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +438 common process_madvise sys_process_madvise > > diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h > > index 433c8c85636e..1b58a11ff49f 100644 > > --- a/include/linux/syscalls.h > > +++ b/include/linux/syscalls.h > > @@ -877,6 +877,8 @@ asmlinkage long sys_munlockall(void); > > asmlinkage long sys_mincore(unsigned long start, size_t len, > > unsigned char __user * vec); > > asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior); > > +asmlinkage long sys_process_madvise(int pidfd, unsigned long start, > > + size_t len, int behavior, unsigned long flags); > > asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, > > unsigned long prot, unsigned long pgoff, > > unsigned long flags); > > diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h > > index 33f3856a9c3c..4bcd8d366f38 100644 > > --- a/include/uapi/asm-generic/unistd.h > > +++ b/include/uapi/asm-generic/unistd.h > > @@ -856,8 +856,11 @@ __SYSCALL(__NR_watch_devices, sys_watch_devices) > > #define __NR_openat2 437 > > __SYSCALL(__NR_openat2, sys_openat2) > > > > +#define __NR_openat2 438 > > +__SYSCALL(__NR_process_madvise, sys_process_madvise) > > + > > #undef __NR_syscalls > > -#define __NR_syscalls 438 > > +#define __NR_syscalls 439 > > > > /* > > * 32 bit systems traditionally used different > > diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c > > index 0e9b275260f8..10ce5eac8b4b 100644 > > --- a/kernel/sys_ni.c > > +++ b/kernel/sys_ni.c > > @@ -281,6 +281,7 @@ COND_SYSCALL(mlockall); > > COND_SYSCALL(munlockall); > > COND_SYSCALL(mincore); > > COND_SYSCALL(madvise); > > +COND_SYSCALL(process_madvise); > > COND_SYSCALL(remap_file_pages); > > COND_SYSCALL(mbind); > > COND_SYSCALL_COMPAT(mbind); > > diff --git a/mm/madvise.c b/mm/madvise.c > > index 0c901de531e4..e15dfb4df7bf 100644 > > --- a/mm/madvise.c > > +++ b/mm/madvise.c > > @@ -17,6 +17,7 @@ > > #include <linux/falloc.h> > > #include <linux/fadvise.h> > > #include <linux/sched.h> > > +#include <linux/sched/mm.h> > > #include <linux/ksm.h> > > #include <linux/fs.h> > > #include <linux/file.h> > > @@ -993,6 +994,18 @@ madvise_behavior_valid(int behavior) > > } > > } > > > > +static bool > > +process_madvise_behavior_valid(int behavior) > > +{ > > + switch (behavior) { > > + case MADV_COLD: > > + case MADV_PAGEOUT: > > + return true; > > + default: > > + return false; > > + } > > +} > > + > > /* > > * madvise_common - request behavior hint to address range of the target process > > * > > @@ -1169,3 +1182,54 @@ SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior) > > { > > return madvise_common(current, current->mm, start, len_in, behavior); > > } > > + > > +SYSCALL_DEFINE5(process_madvise, int, pidfd, unsigned long, start, > > + size_t, len_in, int, behavior, unsigned long, flags) > > I don't like the interface. The fact we have pidfd does not mean, > we have to use it for new syscalls always. A user may want to set > madvise for specific pid from console and pass pid as argument. > pidfd would be an overkill in this case. > We usually call "kill -9 pid" from console. Why shouldn't process_madvise() > allow this? > > I suggent to extend first argument to work with both pid and pidfd. > Look at what we have for waitid(idtype, id_t id, ...) for example: > > idtype == P_PID > Wait for the child whose process ID matches id. > > idtype == P_PIDFD (since Linux 5.4) > Wait for the child referred to by the PID file descriptor specified in id. (See pidfd_open(2) for further information on > PID file descriptors.) > > We may use @flags argument for this. Sorry for chiming in just a comment. Overall, I don't particularly care how or if you integrate pidfd here. One thing I would like to point out is that we're working on a patch to place new features under pidfd specific flags. This e.g. means a pidfd would be only be able to be used for madvise operations (or getfd operations) if it was created with that specific flag set making it easier to share them with other processes. So if you integrate them here I would be quite thankful if you target the patchset for the v5.7 merge window, not for v5.6. Thanks! Christian
On Sat, Jan 11, 2020 at 08:34:52AM +0100, SeongJae Park wrote: > On Fri, 10 Jan 2020 13:34:31 -0800 Minchan Kim <minchan@kernel.org> wrote: > > > There are usecases that System Management Software(SMS) want to give > > a memory hint to other processes because it's not known to the > > application. In the case of Android, ActivityManagerService daemon > > manges app's life cycle and that daemon must be able to initiate > > reclaim on its own without any app involvement. > > > > To solve the issue, this patch introduces new syscall process_madvise(2). > > It uses pidfd of an external processs to give the hint. > > > > int process_madvise(int pidfd, void *addr, size_t length, int advise, > > unsigned long flag); > > > > Since it could affect other process's address range, only privileged > > process(CAP_SYS_PTRACE) or something else(e.g., being the same UID) > > gives it the right to ptrace the process could use it successfully. > > The flag argument is reserved for future use if we need to extend the > > API. > > > > Supporting all hints madvise has/will supported/support to process_madvise > > is rather risky. Because we are not sure all hints make sense from external > > process and implementation for the hint may rely on the caller being > > in the current context so it could be error-prone. Thus, I just limited > > hints as MADV_[COLD|PAGEOUT] in this patch. > > > > If someone want to add other hints, we could hear hear the usecase and > > review it for each hint. It's more safe for maintainace rather than > > introducing a buggy syscall but hard to fix it later. > > > > Signed-off-by: Minchan Kim <minchan@kernel.org> > > --- > > arch/alpha/kernel/syscalls/syscall.tbl | 1 + > > arch/arm/tools/syscall.tbl | 1 + > > arch/arm64/include/asm/unistd.h | 2 +- > > arch/arm64/include/asm/unistd32.h | 2 + > > arch/ia64/kernel/syscalls/syscall.tbl | 1 + > > arch/m68k/kernel/syscalls/syscall.tbl | 1 + > > arch/microblaze/kernel/syscalls/syscall.tbl | 1 + > > arch/mips/kernel/syscalls/syscall_n32.tbl | 1 + > > arch/mips/kernel/syscalls/syscall_n64.tbl | 1 + > > arch/parisc/kernel/syscalls/syscall.tbl | 1 + > > arch/powerpc/kernel/syscalls/syscall.tbl | 1 + > > arch/s390/kernel/syscalls/syscall.tbl | 1 + > > arch/sh/kernel/syscalls/syscall.tbl | 1 + > > arch/sparc/kernel/syscalls/syscall.tbl | 1 + > > arch/x86/entry/syscalls/syscall_32.tbl | 1 + > > arch/x86/entry/syscalls/syscall_64.tbl | 1 + > > arch/xtensa/kernel/syscalls/syscall.tbl | 1 + > > include/linux/syscalls.h | 2 + > > include/uapi/asm-generic/unistd.h | 5 +- > > kernel/sys_ni.c | 1 + > > mm/madvise.c | 64 +++++++++++++++++++++ > > 21 files changed, 89 insertions(+), 2 deletions(-) > > > > diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl > > index e56950f23b49..776c61803315 100644 > > --- a/arch/alpha/kernel/syscalls/syscall.tbl > > +++ b/arch/alpha/kernel/syscalls/syscall.tbl > > @@ -477,3 +477,4 @@ > > # 545 reserved for clone3 > > 546 common watch_devices sys_watch_devices > > 547 common openat2 sys_openat2 > > +548 common process_madvise sys_process_madvise > > diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl > > index 7fb2f4d59210..a43381542276 100644 > > --- a/arch/arm/tools/syscall.tbl > > +++ b/arch/arm/tools/syscall.tbl > > @@ -451,3 +451,4 @@ > > 435 common clone3 sys_clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +438 common process_madvise sys_process_madvise > > diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h > > index 8aa00ccb0b96..b722e47377a5 100644 > > --- a/arch/arm64/include/asm/unistd.h > > +++ b/arch/arm64/include/asm/unistd.h > > @@ -38,7 +38,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 438 > > +#define __NR_compat_syscalls 439 > > #endif > > > > #define __ARCH_WANT_SYS_CLONE > > diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h > > index 31f0ce25719e..5c82557d408f 100644 > > --- a/arch/arm64/include/asm/unistd32.h > > +++ b/arch/arm64/include/asm/unistd32.h > > @@ -883,6 +883,8 @@ __SYSCALL(__NR_clone3, sys_clone3) > > __SYSCALL(__NR_watch_devices, sys_watch_devices) > > #define __NR_openat2 437 > > __SYSCALL(__NR_openat2, sys_openat2) > > +#define __NR_openat2 438 > > Shouldn't this be '#define __NR_process_madvise 438'? > > > +__SYSCALL(__NR_process_madvise, process_madvise) > > > > /* > > * Please add new compat syscalls above this comment and update > > diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl > > index b9aa59931905..c156abc9a298 100644 > > --- a/arch/ia64/kernel/syscalls/syscall.tbl > > +++ b/arch/ia64/kernel/syscalls/syscall.tbl > > @@ -358,3 +358,4 @@ > > # 435 reserved for clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +438 common process_madvise sys_process_madvise > > diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl > > index 868c1ef89d35..5b6034b6650f 100644 > > --- a/arch/m68k/kernel/syscalls/syscall.tbl > > +++ b/arch/m68k/kernel/syscalls/syscall.tbl > > @@ -437,3 +437,4 @@ > > # 435 reserved for clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +438 common process_madvise sys_process_madvise > > diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl > > index 544b4cef18b3..4bef584af09c 100644 > > --- a/arch/microblaze/kernel/syscalls/syscall.tbl > > +++ b/arch/microblaze/kernel/syscalls/syscall.tbl > > @@ -443,3 +443,4 @@ > > 435 common clone3 sys_clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +438 common process_madvise sys_process_madvise > > diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl > > index 05e8aee5dae7..94fbd0fcccce 100644 > > --- a/arch/mips/kernel/syscalls/syscall_n32.tbl > > +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl > > @@ -376,3 +376,4 @@ > > 435 n32 clone3 __sys_clone3 > > 436 n32 watch_devices sys_watch_devices > > 437 n32 openat2 sys_openat2 > > +437 n32 process_madivse sys_process_madvise > > Shouldn't the number for the 'process_madvise' be '438' instead of '437'? > > > diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl > > index 24d6c01328fb..4e6982c429d5 100644 > > --- a/arch/mips/kernel/syscalls/syscall_n64.tbl > > +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl > > @@ -352,3 +352,4 @@ > > 435 n64 clone3 __sys_clone3 > > 436 n64 watch_devices sys_watch_devices > > 437 n64 openat2 sys_openat2 > > +437 n64 process_madvise sys_process_madvise > > 438? Same for below 5 changes. > > > diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl > > index 4b5f77a4e1a2..3aa990caf9dc 100644 > > --- a/arch/parisc/kernel/syscalls/syscall.tbl > > +++ b/arch/parisc/kernel/syscalls/syscall.tbl > > @@ -435,3 +435,4 @@ > > 435 common clone3 sys_clone3_wrapper > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +437 common process_madvise sys_process_madvise > > diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl > > index 9716dc85a517..30e727a23f33 100644 > > --- a/arch/powerpc/kernel/syscalls/syscall.tbl > > +++ b/arch/powerpc/kernel/syscalls/syscall.tbl > > @@ -519,3 +519,4 @@ > > 435 nospu clone3 ppc_clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +437 common process_madvise sys_process_madvise > > diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl > > index 7da330f8b03e..75722e5ff496 100644 > > --- a/arch/s390/kernel/syscalls/syscall.tbl > > +++ b/arch/s390/kernel/syscalls/syscall.tbl > > @@ -440,3 +440,4 @@ > > 435 common clone3 sys_clone3 sys_clone3 > > 436 common watch_devices sys_watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 sys_openat2 > > +437 common process_madvise sys_process_madvise sys_process_madvise > > diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl > > index bb7e68e25337..7d7bc7befad3 100644 > > --- a/arch/sh/kernel/syscalls/syscall.tbl > > +++ b/arch/sh/kernel/syscalls/syscall.tbl > > @@ -440,3 +440,4 @@ > > # 435 reserved for clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +437 common process_madvise sys_process_madvise > > diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl > > index 646a1fad7218..581d331ff62f 100644 > > --- a/arch/sparc/kernel/syscalls/syscall.tbl > > +++ b/arch/sparc/kernel/syscalls/syscall.tbl > > @@ -483,3 +483,4 @@ > > # 435 reserved for clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +437 common process_madvise sys_process_madvise > > diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl > > index 57c53acee290..76a2c266fe7e 100644 > > --- a/arch/x86/entry/syscalls/syscall_32.tbl > > +++ b/arch/x86/entry/syscalls/syscall_32.tbl > > @@ -442,3 +442,4 @@ > > 435 i386 clone3 sys_clone3 __ia32_sys_clone3 > > 436 i386 watch_devices sys_watch_devices __ia32_sys_watch_devices > > 437 i386 openat2 sys_openat2 __ia32_sys_openat2 > > +438 i386 process_madvise sys_process_madvise __ia32_sys_process_madvise > > diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl > > index 1dd8d21f6500..b697cd8620cb 100644 > > --- a/arch/x86/entry/syscalls/syscall_64.tbl > > +++ b/arch/x86/entry/syscalls/syscall_64.tbl > > @@ -359,6 +359,7 @@ > > 435 common clone3 __x64_sys_clone3/ptregs > > 436 common watch_devices __x64_sys_watch_devices > > 437 common openat2 __x64_sys_openat2 > > +438 common process_madvise __x64_sys_process_madvise > > > > # > > # x32-specific system call numbers start at 512 to avoid cache impact > > diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl > > index 0f48ab7bd75b..2e9813ecfd7d 100644 > > --- a/arch/xtensa/kernel/syscalls/syscall.tbl > > +++ b/arch/xtensa/kernel/syscalls/syscall.tbl > > @@ -408,3 +408,4 @@ > > 435 common clone3 sys_clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +438 common process_madvise sys_process_madvise > > diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h > > index 433c8c85636e..1b58a11ff49f 100644 > > --- a/include/linux/syscalls.h > > +++ b/include/linux/syscalls.h > > @@ -877,6 +877,8 @@ asmlinkage long sys_munlockall(void); > > asmlinkage long sys_mincore(unsigned long start, size_t len, > > unsigned char __user * vec); > > asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior); > > +asmlinkage long sys_process_madvise(int pidfd, unsigned long start, > > + size_t len, int behavior, unsigned long flags); > > asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, > > unsigned long prot, unsigned long pgoff, > > unsigned long flags); > > diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h > > index 33f3856a9c3c..4bcd8d366f38 100644 > > --- a/include/uapi/asm-generic/unistd.h > > +++ b/include/uapi/asm-generic/unistd.h > > @@ -856,8 +856,11 @@ __SYSCALL(__NR_watch_devices, sys_watch_devices) > > #define __NR_openat2 437 > > __SYSCALL(__NR_openat2, sys_openat2) > > > > +#define __NR_openat2 438 > > Shouldn't this be '#define __NR_process_madvise 438'? > Hi SeongJae, I fixed all you pointed out. Thanks for the review.
On Mon, Jan 13, 2020 at 11:47:11AM +0300, Kirill Tkhai wrote: > On 11.01.2020 00:34, Minchan Kim wrote: > > There are usecases that System Management Software(SMS) want to give > > a memory hint to other processes because it's not known to the > > application. In the case of Android, ActivityManagerService daemon > > manges app's life cycle and that daemon must be able to initiate > > reclaim on its own without any app involvement. > > > > To solve the issue, this patch introduces new syscall process_madvise(2). > > It uses pidfd of an external processs to give the hint. > > > > int process_madvise(int pidfd, void *addr, size_t length, int advise, > > unsigned long flag); > > > > Since it could affect other process's address range, only privileged > > process(CAP_SYS_PTRACE) or something else(e.g., being the same UID) > > gives it the right to ptrace the process could use it successfully. > > The flag argument is reserved for future use if we need to extend the > > API. > > > > Supporting all hints madvise has/will supported/support to process_madvise > > is rather risky. Because we are not sure all hints make sense from external > > process and implementation for the hint may rely on the caller being > > in the current context so it could be error-prone. Thus, I just limited > > hints as MADV_[COLD|PAGEOUT] in this patch. > > > > If someone want to add other hints, we could hear hear the usecase and > > review it for each hint. It's more safe for maintainace rather than > > introducing a buggy syscall but hard to fix it later. > > > > Signed-off-by: Minchan Kim <minchan@kernel.org> > > --- > > arch/alpha/kernel/syscalls/syscall.tbl | 1 + > > arch/arm/tools/syscall.tbl | 1 + > > arch/arm64/include/asm/unistd.h | 2 +- > > arch/arm64/include/asm/unistd32.h | 2 + > > arch/ia64/kernel/syscalls/syscall.tbl | 1 + > > arch/m68k/kernel/syscalls/syscall.tbl | 1 + > > arch/microblaze/kernel/syscalls/syscall.tbl | 1 + > > arch/mips/kernel/syscalls/syscall_n32.tbl | 1 + > > arch/mips/kernel/syscalls/syscall_n64.tbl | 1 + > > arch/parisc/kernel/syscalls/syscall.tbl | 1 + > > arch/powerpc/kernel/syscalls/syscall.tbl | 1 + > > arch/s390/kernel/syscalls/syscall.tbl | 1 + > > arch/sh/kernel/syscalls/syscall.tbl | 1 + > > arch/sparc/kernel/syscalls/syscall.tbl | 1 + > > arch/x86/entry/syscalls/syscall_32.tbl | 1 + > > arch/x86/entry/syscalls/syscall_64.tbl | 1 + > > arch/xtensa/kernel/syscalls/syscall.tbl | 1 + > > include/linux/syscalls.h | 2 + > > include/uapi/asm-generic/unistd.h | 5 +- > > kernel/sys_ni.c | 1 + > > mm/madvise.c | 64 +++++++++++++++++++++ > > 21 files changed, 89 insertions(+), 2 deletions(-) > > > > diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl > > index e56950f23b49..776c61803315 100644 > > --- a/arch/alpha/kernel/syscalls/syscall.tbl > > +++ b/arch/alpha/kernel/syscalls/syscall.tbl > > @@ -477,3 +477,4 @@ > > # 545 reserved for clone3 > > 546 common watch_devices sys_watch_devices > > 547 common openat2 sys_openat2 > > +548 common process_madvise sys_process_madvise > > diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl > > index 7fb2f4d59210..a43381542276 100644 > > --- a/arch/arm/tools/syscall.tbl > > +++ b/arch/arm/tools/syscall.tbl > > @@ -451,3 +451,4 @@ > > 435 common clone3 sys_clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +438 common process_madvise sys_process_madvise > > diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h > > index 8aa00ccb0b96..b722e47377a5 100644 > > --- a/arch/arm64/include/asm/unistd.h > > +++ b/arch/arm64/include/asm/unistd.h > > @@ -38,7 +38,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 438 > > +#define __NR_compat_syscalls 439 > > #endif > > > > #define __ARCH_WANT_SYS_CLONE > > diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h > > index 31f0ce25719e..5c82557d408f 100644 > > --- a/arch/arm64/include/asm/unistd32.h > > +++ b/arch/arm64/include/asm/unistd32.h > > @@ -883,6 +883,8 @@ __SYSCALL(__NR_clone3, sys_clone3) > > __SYSCALL(__NR_watch_devices, sys_watch_devices) > > #define __NR_openat2 437 > > __SYSCALL(__NR_openat2, sys_openat2) > > +#define __NR_openat2 438 > > +__SYSCALL(__NR_process_madvise, process_madvise) > > > > /* > > * Please add new compat syscalls above this comment and update > > diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl > > index b9aa59931905..c156abc9a298 100644 > > --- a/arch/ia64/kernel/syscalls/syscall.tbl > > +++ b/arch/ia64/kernel/syscalls/syscall.tbl > > @@ -358,3 +358,4 @@ > > # 435 reserved for clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +438 common process_madvise sys_process_madvise > > diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl > > index 868c1ef89d35..5b6034b6650f 100644 > > --- a/arch/m68k/kernel/syscalls/syscall.tbl > > +++ b/arch/m68k/kernel/syscalls/syscall.tbl > > @@ -437,3 +437,4 @@ > > # 435 reserved for clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +438 common process_madvise sys_process_madvise > > diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl > > index 544b4cef18b3..4bef584af09c 100644 > > --- a/arch/microblaze/kernel/syscalls/syscall.tbl > > +++ b/arch/microblaze/kernel/syscalls/syscall.tbl > > @@ -443,3 +443,4 @@ > > 435 common clone3 sys_clone3 > > 436 common watch_devices sys_watch_devices > > 437 common openat2 sys_openat2 > > +438 common process_madvise sys_process_madvise > > diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl > > index 05e8aee5dae7..94fbd0fcccce 100644 > > --- a/arch/mips/kernel/syscalls/syscall_n32.tbl > > +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl > > @@ -376,3 +376,4 @@ > > 435 n32 clone3 __sys_clone3 > > 436 n32 watch_devices sys_watch_devices > > 437 n32 openat2 sys_openat2 > > +437 n32 process_madivse sys_process_madvise > > 438. And several places below has the same mistake. Thanks. I fixed. < snip > > > diff --git a/mm/madvise.c b/mm/madvise.c > > index 0c901de531e4..e15dfb4df7bf 100644 > > --- a/mm/madvise.c > > +++ b/mm/madvise.c > > @@ -17,6 +17,7 @@ > > #include <linux/falloc.h> > > #include <linux/fadvise.h> > > #include <linux/sched.h> > > +#include <linux/sched/mm.h> > > #include <linux/ksm.h> > > #include <linux/fs.h> > > #include <linux/file.h> > > @@ -993,6 +994,18 @@ madvise_behavior_valid(int behavior) > > } > > } > > > > +static bool > > +process_madvise_behavior_valid(int behavior) > > +{ > > + switch (behavior) { > > + case MADV_COLD: > > + case MADV_PAGEOUT: > > + return true; > > + default: > > + return false; > > + } > > +} > > + > > /* > > * madvise_common - request behavior hint to address range of the target process > > * > > @@ -1169,3 +1182,54 @@ SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior) > > { > > return madvise_common(current, current->mm, start, len_in, behavior); > > } > > + > > +SYSCALL_DEFINE5(process_madvise, int, pidfd, unsigned long, start, > > + size_t, len_in, int, behavior, unsigned long, flags) > > I don't like the interface. The fact we have pidfd does not mean, > we have to use it for new syscalls always. A user may want to set > madvise for specific pid from console and pass pid as argument. > pidfd would be an overkill in this case. I am curious what is our plan for pid and pidfd once we introduced pidfd. Ccing pidfd maintainer. Since pid has clear problems, pidfd was born so not sure we should keep both options for new coming API. Since this is hinting API, performance wouldn't be critical requirment. Rather than, it aims for a certain target process so that keep the process during the operation without concern of reusing pid, which is perfectly matched with pidfd. > We usually call "kill -9 pid" from console. Why shouldn't process_madvise() > allow this? It's a syscall but not command which uses the syscall for implementation. > > I suggent to extend first argument to work with both pid and pidfd. > Look at what we have for waitid(idtype, id_t id, ...) for example: > > idtype == P_PID > Wait for the child whose process ID matches id. > > idtype == P_PIDFD (since Linux 5.4) > Wait for the child referred to by the PID file descriptor specified in id. (See pidfd_open(2) for further information on > PID file descriptors.) IMO, it's okay to extend existing syscall to support new pidfd but I'm not convinced why we should support both options for this memory hinting API fron the beginning. I'm not strong against of supporting both options but it would be much better to have strong justification or guide whehter we should support both or only pidfd so that upcoming APIs will follow the strategy. > > We may use @flags argument for this. > > > +{ > > + int ret; > > + struct fd f; > > + struct pid *pid; > > + struct task_struct *task; > > + struct mm_struct *mm; > > + > > + if (flags != 0) > > + return -EINVAL; > > + > > + if (!process_madvise_behavior_valid(behavior)) > > + return -EINVAL; > > + > > + f = fdget(pidfd); > > + if (!f.file) > > + return -EBADF; > > + > > + pid = pidfd_pid(f.file); > > + if (IS_ERR(pid)) { > > + ret = PTR_ERR(pid); > > + goto err; > > + } > > From here: > > > + rcu_read_lock(); > > + task = pid_task(pid, PIDTYPE_PID); > > + if (!task) { > > + rcu_read_unlock(); > > + ret = -ESRCH; > > + goto err; > > + } > > + > > + get_task_struct(task); > > + rcu_read_unlock(); > > to here your code is a copy of existing get_pid_task(). We should the primitive instead. Fixed. > > > + > > + mm = mm_access(task, PTRACE_MODE_ATTACH_FSCREDS); > > + if (IS_ERR_OR_NULL(mm)) { > > + ret = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH; > > + goto release_task; > > + } > > + > > + ret = madvise_common(task, mm, start, len_in, behavior); > > + mmput(mm); > > +release_task: > > + put_task_struct(task); > > +err: > > Maybe s/err:/fdput:/ for uniformity with the above "release_task:"? Fixed. Thanks for the review.
On Mon, Jan 13, 2020 at 11:42:57AM +0100, Christian Brauner wrote: > On Mon, Jan 13, 2020 at 11:47:11AM +0300, Kirill Tkhai wrote: < snip > > > > +SYSCALL_DEFINE5(process_madvise, int, pidfd, unsigned long, start, > > > + size_t, len_in, int, behavior, unsigned long, flags) > > > > I don't like the interface. The fact we have pidfd does not mean, > > we have to use it for new syscalls always. A user may want to set > > madvise for specific pid from console and pass pid as argument. > > pidfd would be an overkill in this case. > > We usually call "kill -9 pid" from console. Why shouldn't process_madvise() > > allow this? > > > > I suggent to extend first argument to work with both pid and pidfd. > > Look at what we have for waitid(idtype, id_t id, ...) for example: > > > > idtype == P_PID > > Wait for the child whose process ID matches id. > > > > idtype == P_PIDFD (since Linux 5.4) > > Wait for the child referred to by the PID file descriptor specified in id. (See pidfd_open(2) for further information on > > PID file descriptors.) > > > > We may use @flags argument for this. > > Sorry for chiming in just a comment. Overall, I don't particularly care > how or if you integrate pidfd here. One thing I would like to point out > is that we're working on a patch to place new features under pidfd > specific flags. This e.g. means a pidfd would be only be able to be used > for madvise operations (or getfd operations) if it was created with that > specific flag set making it easier to share them with other processes. > So if you integrate them here I would be quite thankful if you target > the patchset for the v5.7 merge window, not for v5.6. Hi Christian, Sorry but I couldn't understand your point. Could you clarify what you meant? Thanks.
On Mon, Jan 13, 2020 at 10:44:08AM -0800, Minchan Kim wrote: > On Mon, Jan 13, 2020 at 11:42:57AM +0100, Christian Brauner wrote: > > On Mon, Jan 13, 2020 at 11:47:11AM +0300, Kirill Tkhai wrote: > > < snip > > > > > > +SYSCALL_DEFINE5(process_madvise, int, pidfd, unsigned long, start, > > > > + size_t, len_in, int, behavior, unsigned long, flags) > > > > > > I don't like the interface. The fact we have pidfd does not mean, > > > we have to use it for new syscalls always. A user may want to set > > > madvise for specific pid from console and pass pid as argument. > > > pidfd would be an overkill in this case. > > > We usually call "kill -9 pid" from console. Why shouldn't process_madvise() > > > allow this? > > > > > > I suggent to extend first argument to work with both pid and pidfd. > > > Look at what we have for waitid(idtype, id_t id, ...) for example: > > > > > > idtype == P_PID > > > Wait for the child whose process ID matches id. > > > > > > idtype == P_PIDFD (since Linux 5.4) > > > Wait for the child referred to by the PID file descriptor specified in id. (See pidfd_open(2) for further information on > > > PID file descriptors.) > > > > > > We may use @flags argument for this. > > > > Sorry for chiming in just a comment. Overall, I don't particularly care > > how or if you integrate pidfd here. One thing I would like to point out > > is that we're working on a patch to place new features under pidfd > > specific flags. This e.g. means a pidfd would be only be able to be used > > for madvise operations (or getfd operations) if it was created with that > > specific flag set making it easier to share them with other processes. > > So if you integrate them here I would be quite thankful if you target > > the patchset for the v5.7 merge window, not for v5.6. > > Hi Christian, > Sorry but I couldn't understand your point. > Could you clarify what you meant? Hi Minchan, Sure. When you create a pidfd, e.g. with clone3() and you'd wanted to use it for madvise you'd need to set a flag like pidfd_cap_madvise or pidfd_feature_madvise when you create the pidfd. Only if the pidfd was created with that flag set could you use it with madvise (This does not affect the permission checking you're performing here.). This has come up a couple of times and becomes more relevant now that people keep adding new features on top of pidfd and is similar to what we are now doing with openat2(). Christian
On Mon, Jan 13, 2020, 12:47 AM Kirill Tkhai <ktkhai@virtuozzo.com> wrote: > > +SYSCALL_DEFINE5(process_madvise, int, pidfd, unsigned long, start, > > + size_t, len_in, int, behavior, unsigned long, flags) > > I don't like the interface. The fact we have pidfd does not mean, > we have to use it for new syscalls always. A user may want to set > madvise for specific pid from console and pass pid as argument. > pidfd would be an overkill in this case. > We usually call "kill -9 pid" from console. Why shouldn't process_madvise() > allow this? All new APIs should use pidfds: they're better than numeric PIDs in every way. If a program wants to allow users to specify processes by numeric PID, it can parse that numeric PID, open the corresponding pidfd, and then use that pidfd with whatever system call it wants. It's not necessary to support numeric PIDs at the system call level to allow a console program to identify a process by numeric PID.
On Mon, Jan 13, 2020 at 11:10 AM Christian Brauner <christian.brauner@ubuntu.com> wrote: > This does not > affect the permission checking you're performing here. Pidfds-as-capabilities sounds like a good change. Can you clarify what you mean here though? Do you mean that in order to perform some process-directed operation X on process Y, the pidfd passed to X must have been opened with PIDFD_CAP_X *and* the process *using* the pidfds must be able to perform operation X on process Y? Or do pidfds in this model "carry" permissions in the same way that an ordinary file descriptor "carries" the ability to write to a file if it was opened with O_WRONLY even if the FD is passed to a process that couldn't otherwise write to that file? Right now, pidfds are identity-only and always rely on the caller's permissions. I like the capability bit model because it makes pidfds more consistent with other file descriptors and enabled delegation of capabilities across the system.
On Mon, Jan 13, 2020 at 11:27:03AM -0800, Daniel Colascione wrote: > On Mon, Jan 13, 2020 at 11:10 AM Christian Brauner > <christian.brauner@ubuntu.com> wrote: > > This does not > > affect the permission checking you're performing here. > > Pidfds-as-capabilities sounds like a good change. Can you clarify what > you mean here though? Do you mean that in order to perform some > process-directed operation X on process Y, the pidfd passed to X must > have been opened with PIDFD_CAP_X *and* the process *using* the pidfds > must be able to perform operation X on process Y? Or do pidfds in this > model "carry" permissions in the same way that an ordinary file > descriptor "carries" the ability to write to a file if it was opened > with O_WRONLY even if the FD is passed to a process that couldn't > otherwise write to that file? Right now, pidfds are identity-only and > always rely on the caller's permissions. I like the capability bit > model because it makes pidfds more consistent with other file > descriptors and enabled delegation of capabilities across the system. I'm going back and forth on this. My initial implementation has it that you'd need both, PIDFD_FLAG/CAP_X and the process using the pidfd must be able to perform the operation X on process Y. The alternative becomes tricky for e.g. anything that requires ptrace_may_access() permissions such as getting an fd out from another task based on its pidfd and so on. Christian
On Mon, Jan 13, 2020 at 12:42 PM Christian Brauner <christian.brauner@ubuntu.com> wrote: > > On Mon, Jan 13, 2020 at 11:27:03AM -0800, Daniel Colascione wrote: > > On Mon, Jan 13, 2020 at 11:10 AM Christian Brauner > > <christian.brauner@ubuntu.com> wrote: > > > This does not > > > affect the permission checking you're performing here. > > > > Pidfds-as-capabilities sounds like a good change. Can you clarify what > > you mean here though? Do you mean that in order to perform some > > process-directed operation X on process Y, the pidfd passed to X must > > have been opened with PIDFD_CAP_X *and* the process *using* the pidfds > > must be able to perform operation X on process Y? Or do pidfds in this > > model "carry" permissions in the same way that an ordinary file > > descriptor "carries" the ability to write to a file if it was opened > > with O_WRONLY even if the FD is passed to a process that couldn't > > otherwise write to that file? Right now, pidfds are identity-only and > > always rely on the caller's permissions. I like the capability bit > > model because it makes pidfds more consistent with other file > > descriptors and enabled delegation of capabilities across the system. > > I'm going back and forth on this. My initial implementation has it that > you'd need both, PIDFD_FLAG/CAP_X and the process using the pidfd must > be able to perform the operation X on process Y. The alternative becomes > tricky for e.g. anything that requires ptrace_may_access() permissions > such as getting an fd out from another task based on its pidfd and so > on. I think the alternative is necessary though. What's the point of the pidfd capability bits if they don't grant access? If I have a pidfd for Y that doesn't let me do operation X, but I have ambient authority to do Y anyway, then I can just make my own pidfd for Y and then use that new pidfd to do X. AFAICT, pidfd capabilities only do something when they replace ptrace_may_access and friends for access control. Otherwise, they seem purely advisory. Am I missing something?
On 13.01.2020 22:18, Daniel Colascione wrote: > On Mon, Jan 13, 2020, 12:47 AM Kirill Tkhai <ktkhai@virtuozzo.com> wrote: >>> +SYSCALL_DEFINE5(process_madvise, int, pidfd, unsigned long, start, >>> + size_t, len_in, int, behavior, unsigned long, flags) >> >> I don't like the interface. The fact we have pidfd does not mean, >> we have to use it for new syscalls always. A user may want to set >> madvise for specific pid from console and pass pid as argument. >> pidfd would be an overkill in this case. >> We usually call "kill -9 pid" from console. Why shouldn't process_madvise() >> allow this? > > All new APIs should use pidfds: they're better than numeric PIDs Yes > in every way. No > If a program wants to allow users to specify processes by > numeric PID, it can parse that numeric PID, open the corresponding > pidfd, and then use that pidfd with whatever system call it wants. > It's not necessary to support numeric PIDs at the system call level to > allow a console program to identify a process by numeric PID. No. It is overkill. Ordinary pid interfaces also should be available. There are a lot of cases, when they are more comfortable. Say, a calling of process_madvise() from tracer, when a tracee is stopped. In this moment the tracer knows everything about tracee state, and pidfd brackets pidfd_open() and close() around actual action look just stupid, and this is cpu time wasting. Another example is a parent task, which manages parameters of its children. It knows everything about them, whether they are alive or not. Pidfd interface will just utilize additional cpu time here. So, no. Both interfaces should be available.
Hi Christian, On Mon, Jan 13, 2020 at 08:10:47PM +0100, Christian Brauner wrote: > On Mon, Jan 13, 2020 at 10:44:08AM -0800, Minchan Kim wrote: > > On Mon, Jan 13, 2020 at 11:42:57AM +0100, Christian Brauner wrote: > > > On Mon, Jan 13, 2020 at 11:47:11AM +0300, Kirill Tkhai wrote: > > > > < snip > > > > > > > > +SYSCALL_DEFINE5(process_madvise, int, pidfd, unsigned long, start, > > > > > + size_t, len_in, int, behavior, unsigned long, flags) > > > > > > > > I don't like the interface. The fact we have pidfd does not mean, > > > > we have to use it for new syscalls always. A user may want to set > > > > madvise for specific pid from console and pass pid as argument. > > > > pidfd would be an overkill in this case. > > > > We usually call "kill -9 pid" from console. Why shouldn't process_madvise() > > > > allow this? > > > > > > > > I suggent to extend first argument to work with both pid and pidfd. > > > > Look at what we have for waitid(idtype, id_t id, ...) for example: > > > > > > > > idtype == P_PID > > > > Wait for the child whose process ID matches id. > > > > > > > > idtype == P_PIDFD (since Linux 5.4) > > > > Wait for the child referred to by the PID file descriptor specified in id. (See pidfd_open(2) for further information on > > > > PID file descriptors.) > > > > > > > > We may use @flags argument for this. > > > > > > Sorry for chiming in just a comment. Overall, I don't particularly care > > > how or if you integrate pidfd here. One thing I would like to point out > > > is that we're working on a patch to place new features under pidfd > > > specific flags. This e.g. means a pidfd would be only be able to be used > > > for madvise operations (or getfd operations) if it was created with that > > > specific flag set making it easier to share them with other processes. > > > So if you integrate them here I would be quite thankful if you target > > > the patchset for the v5.7 merge window, not for v5.6. > > > > Hi Christian, > > Sorry but I couldn't understand your point. > > Could you clarify what you meant? > > Hi Minchan, > > Sure. When you create a pidfd, e.g. with clone3() and you'd wanted to > use it for madvise you'd need to set a flag like pidfd_cap_madvise or > pidfd_feature_madvise when you create the pidfd. Only if the pidfd was > created with that flag set could you use it with madvise (This does not > affect the permission checking you're performing here.). This has come > up a couple of times and becomes more relevant now that people keep > adding new features on top of pidfd and is similar to what we are now > doing with openat2(). Thanks for the explain. When I read discussion with you and Daniel, it's still vague for me that what's the outcome so that it could land onto v5.6.(If I miss something progress on other thread, sorry about that.) I will keep Ccing you so that you may notice when this patchset could be merged(Please Cc me when you send your patchset for me to notice) So if we judge it's worth to integrate, maybe we could make a quick patch to use it or postpone a cycle to intergrate it if we have more time. Thanks.
On Tue, Jan 14, 2020 at 11:39:28AM +0300, Kirill Tkhai wrote: > On 13.01.2020 22:18, Daniel Colascione wrote: > > On Mon, Jan 13, 2020, 12:47 AM Kirill Tkhai <ktkhai@virtuozzo.com> wrote: > >>> +SYSCALL_DEFINE5(process_madvise, int, pidfd, unsigned long, start, > >>> + size_t, len_in, int, behavior, unsigned long, flags) > >> > >> I don't like the interface. The fact we have pidfd does not mean, > >> we have to use it for new syscalls always. A user may want to set > >> madvise for specific pid from console and pass pid as argument. > >> pidfd would be an overkill in this case. > >> We usually call "kill -9 pid" from console. Why shouldn't process_madvise() > >> allow this? > > > > All new APIs should use pidfds: they're better than numeric PIDs > > Yes > > > in every way. > > No > > > If a program wants to allow users to specify processes by > > numeric PID, it can parse that numeric PID, open the corresponding > > pidfd, and then use that pidfd with whatever system call it wants. > > It's not necessary to support numeric PIDs at the system call level to > > allow a console program to identify a process by numeric PID. > > No. It is overkill. Ordinary pid interfaces also should be available. > There are a lot of cases, when they are more comfortable. Say, a calling > of process_madvise() from tracer, when a tracee is stopped. In this moment > the tracer knows everything about tracee state, and pidfd brackets > pidfd_open() and close() around actual action look just stupid, and this > is cpu time wasting. > > Another example is a parent task, which manages parameters of its children. > It knows everything about them, whether they are alive or not. Pidfd interface > will just utilize additional cpu time here. > > So, no. Both interfaces should be available. Sounds like that you want to support both options for every upcoming API which deals with pid. I'm not sure how it's critical for process_madvise API this case. In general, we sacrifice some performance for the nicer one and later, once it's reported as hurdle for some workload, we could fix it via introducing new flag. What I don't like at this moment is to make syscall complicated with potential scenarios without real workload.
On Mon, Jan 13, 2020 at 01:04:44PM -0800, Daniel Colascione wrote: > On Mon, Jan 13, 2020 at 12:42 PM Christian Brauner > <christian.brauner@ubuntu.com> wrote: > > > > On Mon, Jan 13, 2020 at 11:27:03AM -0800, Daniel Colascione wrote: > > > On Mon, Jan 13, 2020 at 11:10 AM Christian Brauner > > > <christian.brauner@ubuntu.com> wrote: > > > > This does not > > > > affect the permission checking you're performing here. > > > > > > Pidfds-as-capabilities sounds like a good change. Can you clarify what > > > you mean here though? Do you mean that in order to perform some > > > process-directed operation X on process Y, the pidfd passed to X must > > > have been opened with PIDFD_CAP_X *and* the process *using* the pidfds > > > must be able to perform operation X on process Y? Or do pidfds in this > > > model "carry" permissions in the same way that an ordinary file > > > descriptor "carries" the ability to write to a file if it was opened > > > with O_WRONLY even if the FD is passed to a process that couldn't > > > otherwise write to that file? Right now, pidfds are identity-only and > > > always rely on the caller's permissions. I like the capability bit > > > model because it makes pidfds more consistent with other file > > > descriptors and enabled delegation of capabilities across the system. > > > > I'm going back and forth on this. My initial implementation has it that > > you'd need both, PIDFD_FLAG/CAP_X and the process using the pidfd must > > be able to perform the operation X on process Y. The alternative becomes > > tricky for e.g. anything that requires ptrace_may_access() permissions > > such as getting an fd out from another task based on its pidfd and so > > on. > > I think the alternative is necessary though. What's the point of the > pidfd capability bits if they don't grant access? If I have a pidfd > for Y that doesn't let me do operation X, but I have ambient authority > to do Y anyway, then I can just make my own pidfd for Y and then use > that new pidfd to do X. AFAICT, pidfd capabilities only do something > when they replace ptrace_may_access and friends for access control. > Otherwise, they seem purely advisory. Am I missing something? (Sorry for the late reply. It's kinda busy atm.) Yes, I think the best option is to explore the possibility to make them act similar to open(). I'll try to post patches soon. Christian
On Tue, Jan 14, 2020 at 10:59:44AM -0800, Minchan Kim wrote: > Hi Christian, > > On Mon, Jan 13, 2020 at 08:10:47PM +0100, Christian Brauner wrote: > > On Mon, Jan 13, 2020 at 10:44:08AM -0800, Minchan Kim wrote: > > > On Mon, Jan 13, 2020 at 11:42:57AM +0100, Christian Brauner wrote: > > > > On Mon, Jan 13, 2020 at 11:47:11AM +0300, Kirill Tkhai wrote: > > > > > > < snip > > > > > > > > > > +SYSCALL_DEFINE5(process_madvise, int, pidfd, unsigned long, start, > > > > > > + size_t, len_in, int, behavior, unsigned long, flags) > > > > > > > > > > I don't like the interface. The fact we have pidfd does not mean, > > > > > we have to use it for new syscalls always. A user may want to set > > > > > madvise for specific pid from console and pass pid as argument. > > > > > pidfd would be an overkill in this case. > > > > > We usually call "kill -9 pid" from console. Why shouldn't process_madvise() > > > > > allow this? > > > > > > > > > > I suggent to extend first argument to work with both pid and pidfd. > > > > > Look at what we have for waitid(idtype, id_t id, ...) for example: > > > > > > > > > > idtype == P_PID > > > > > Wait for the child whose process ID matches id. > > > > > > > > > > idtype == P_PIDFD (since Linux 5.4) > > > > > Wait for the child referred to by the PID file descriptor specified in id. (See pidfd_open(2) for further information on > > > > > PID file descriptors.) > > > > > > > > > > We may use @flags argument for this. > > > > > > > > Sorry for chiming in just a comment. Overall, I don't particularly care > > > > how or if you integrate pidfd here. One thing I would like to point out > > > > is that we're working on a patch to place new features under pidfd > > > > specific flags. This e.g. means a pidfd would be only be able to be used > > > > for madvise operations (or getfd operations) if it was created with that > > > > specific flag set making it easier to share them with other processes. > > > > So if you integrate them here I would be quite thankful if you target > > > > the patchset for the v5.7 merge window, not for v5.6. > > > > > > Hi Christian, > > > Sorry but I couldn't understand your point. > > > Could you clarify what you meant? > > > > Hi Minchan, > > > > Sure. When you create a pidfd, e.g. with clone3() and you'd wanted to > > use it for madvise you'd need to set a flag like pidfd_cap_madvise or > > pidfd_feature_madvise when you create the pidfd. Only if the pidfd was > > created with that flag set could you use it with madvise (This does not > > affect the permission checking you're performing here.). This has come > > up a couple of times and becomes more relevant now that people keep > > adding new features on top of pidfd and is similar to what we are now > > doing with openat2(). > > Thanks for the explain. When I read discussion with you and Daniel, it's > still vague for me that what's the outcome so that it could land onto > v5.6.(If I miss something progress on other thread, sorry about that.) I'll try to post patches soon. > > I will keep Ccing you so that you may notice when this patchset could > be merged(Please Cc me when you send your patchset for me to notice) > So if we judge it's worth to integrate, maybe we could make a quick > patch to use it or postpone a cycle to intergrate it if we have more > time. Yeah, that would be great! It's unlikely that process_madvise() will land for v5.6 anyway since it's quite late in the cycle, so we should have some time to coordinate. Thanks! Christian
On 14.01.2020 22:12, Minchan Kim wrote: > On Tue, Jan 14, 2020 at 11:39:28AM +0300, Kirill Tkhai wrote: >> On 13.01.2020 22:18, Daniel Colascione wrote: >>> On Mon, Jan 13, 2020, 12:47 AM Kirill Tkhai <ktkhai@virtuozzo.com> wrote: >>>>> +SYSCALL_DEFINE5(process_madvise, int, pidfd, unsigned long, start, >>>>> + size_t, len_in, int, behavior, unsigned long, flags) >>>> >>>> I don't like the interface. The fact we have pidfd does not mean, >>>> we have to use it for new syscalls always. A user may want to set >>>> madvise for specific pid from console and pass pid as argument. >>>> pidfd would be an overkill in this case. >>>> We usually call "kill -9 pid" from console. Why shouldn't process_madvise() >>>> allow this? >>> >>> All new APIs should use pidfds: they're better than numeric PIDs >> >> Yes >> >>> in every way. >> >> No >> >>> If a program wants to allow users to specify processes by >>> numeric PID, it can parse that numeric PID, open the corresponding >>> pidfd, and then use that pidfd with whatever system call it wants. >>> It's not necessary to support numeric PIDs at the system call level to >>> allow a console program to identify a process by numeric PID. >> >> No. It is overkill. Ordinary pid interfaces also should be available. >> There are a lot of cases, when they are more comfortable. Say, a calling >> of process_madvise() from tracer, when a tracee is stopped. In this moment >> the tracer knows everything about tracee state, and pidfd brackets >> pidfd_open() and close() around actual action look just stupid, and this >> is cpu time wasting. >> >> Another example is a parent task, which manages parameters of its children. >> It knows everything about them, whether they are alive or not. Pidfd interface >> will just utilize additional cpu time here. >> >> So, no. Both interfaces should be available. > > Sounds like that you want to support both options for every upcoming API > which deals with pid. I'm not sure how it's critical for process_madvise > API this case. In general, we sacrifice some performance for the nicer one > and later, once it's reported as hurdle for some workload, we could fix it > via introducing new flag. What I don't like at this moment is to make > syscall complicated with potential scenarios without real workload. Yes, I suggest allowing both options for every new process api. This may be performance-critical for some workloads. Say, CRIU may exercise a lot of inter-process calls during container restore and additional system calls will slow down online migration. And there should be many another examples. At least you have to call the first argument in more generic way from the start. Not "int pidfd", but something like "idtype_t id" instead. This allows to extend it in the future. Kirill
diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl index e56950f23b49..776c61803315 100644 --- a/arch/alpha/kernel/syscalls/syscall.tbl +++ b/arch/alpha/kernel/syscalls/syscall.tbl @@ -477,3 +477,4 @@ # 545 reserved for clone3 546 common watch_devices sys_watch_devices 547 common openat2 sys_openat2 +548 common process_madvise sys_process_madvise diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index 7fb2f4d59210..a43381542276 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -451,3 +451,4 @@ 435 common clone3 sys_clone3 436 common watch_devices sys_watch_devices 437 common openat2 sys_openat2 +438 common process_madvise sys_process_madvise diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index 8aa00ccb0b96..b722e47377a5 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -38,7 +38,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 438 +#define __NR_compat_syscalls 439 #endif #define __ARCH_WANT_SYS_CLONE diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index 31f0ce25719e..5c82557d408f 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h @@ -883,6 +883,8 @@ __SYSCALL(__NR_clone3, sys_clone3) __SYSCALL(__NR_watch_devices, sys_watch_devices) #define __NR_openat2 437 __SYSCALL(__NR_openat2, sys_openat2) +#define __NR_openat2 438 +__SYSCALL(__NR_process_madvise, process_madvise) /* * Please add new compat syscalls above this comment and update diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl index b9aa59931905..c156abc9a298 100644 --- a/arch/ia64/kernel/syscalls/syscall.tbl +++ b/arch/ia64/kernel/syscalls/syscall.tbl @@ -358,3 +358,4 @@ # 435 reserved for clone3 436 common watch_devices sys_watch_devices 437 common openat2 sys_openat2 +438 common process_madvise sys_process_madvise diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl index 868c1ef89d35..5b6034b6650f 100644 --- a/arch/m68k/kernel/syscalls/syscall.tbl +++ b/arch/m68k/kernel/syscalls/syscall.tbl @@ -437,3 +437,4 @@ # 435 reserved for clone3 436 common watch_devices sys_watch_devices 437 common openat2 sys_openat2 +438 common process_madvise sys_process_madvise diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl index 544b4cef18b3..4bef584af09c 100644 --- a/arch/microblaze/kernel/syscalls/syscall.tbl +++ b/arch/microblaze/kernel/syscalls/syscall.tbl @@ -443,3 +443,4 @@ 435 common clone3 sys_clone3 436 common watch_devices sys_watch_devices 437 common openat2 sys_openat2 +438 common process_madvise sys_process_madvise diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl index 05e8aee5dae7..94fbd0fcccce 100644 --- a/arch/mips/kernel/syscalls/syscall_n32.tbl +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl @@ -376,3 +376,4 @@ 435 n32 clone3 __sys_clone3 436 n32 watch_devices sys_watch_devices 437 n32 openat2 sys_openat2 +437 n32 process_madivse sys_process_madvise diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl index 24d6c01328fb..4e6982c429d5 100644 --- a/arch/mips/kernel/syscalls/syscall_n64.tbl +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl @@ -352,3 +352,4 @@ 435 n64 clone3 __sys_clone3 436 n64 watch_devices sys_watch_devices 437 n64 openat2 sys_openat2 +437 n64 process_madvise sys_process_madvise diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl index 4b5f77a4e1a2..3aa990caf9dc 100644 --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -435,3 +435,4 @@ 435 common clone3 sys_clone3_wrapper 436 common watch_devices sys_watch_devices 437 common openat2 sys_openat2 +437 common process_madvise sys_process_madvise diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl index 9716dc85a517..30e727a23f33 100644 --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -519,3 +519,4 @@ 435 nospu clone3 ppc_clone3 436 common watch_devices sys_watch_devices 437 common openat2 sys_openat2 +437 common process_madvise sys_process_madvise diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl index 7da330f8b03e..75722e5ff496 100644 --- a/arch/s390/kernel/syscalls/syscall.tbl +++ b/arch/s390/kernel/syscalls/syscall.tbl @@ -440,3 +440,4 @@ 435 common clone3 sys_clone3 sys_clone3 436 common watch_devices sys_watch_devices sys_watch_devices 437 common openat2 sys_openat2 sys_openat2 +437 common process_madvise sys_process_madvise sys_process_madvise diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl index bb7e68e25337..7d7bc7befad3 100644 --- a/arch/sh/kernel/syscalls/syscall.tbl +++ b/arch/sh/kernel/syscalls/syscall.tbl @@ -440,3 +440,4 @@ # 435 reserved for clone3 436 common watch_devices sys_watch_devices 437 common openat2 sys_openat2 +437 common process_madvise sys_process_madvise diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl index 646a1fad7218..581d331ff62f 100644 --- a/arch/sparc/kernel/syscalls/syscall.tbl +++ b/arch/sparc/kernel/syscalls/syscall.tbl @@ -483,3 +483,4 @@ # 435 reserved for clone3 436 common watch_devices sys_watch_devices 437 common openat2 sys_openat2 +437 common process_madvise sys_process_madvise diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index 57c53acee290..76a2c266fe7e 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -442,3 +442,4 @@ 435 i386 clone3 sys_clone3 __ia32_sys_clone3 436 i386 watch_devices sys_watch_devices __ia32_sys_watch_devices 437 i386 openat2 sys_openat2 __ia32_sys_openat2 +438 i386 process_madvise sys_process_madvise __ia32_sys_process_madvise diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 1dd8d21f6500..b697cd8620cb 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -359,6 +359,7 @@ 435 common clone3 __x64_sys_clone3/ptregs 436 common watch_devices __x64_sys_watch_devices 437 common openat2 __x64_sys_openat2 +438 common process_madvise __x64_sys_process_madvise # # x32-specific system call numbers start at 512 to avoid cache impact diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl index 0f48ab7bd75b..2e9813ecfd7d 100644 --- a/arch/xtensa/kernel/syscalls/syscall.tbl +++ b/arch/xtensa/kernel/syscalls/syscall.tbl @@ -408,3 +408,4 @@ 435 common clone3 sys_clone3 436 common watch_devices sys_watch_devices 437 common openat2 sys_openat2 +438 common process_madvise sys_process_madvise diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 433c8c85636e..1b58a11ff49f 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -877,6 +877,8 @@ asmlinkage long sys_munlockall(void); asmlinkage long sys_mincore(unsigned long start, size_t len, unsigned char __user * vec); asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior); +asmlinkage long sys_process_madvise(int pidfd, unsigned long start, + size_t len, int behavior, unsigned long flags); asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long flags); diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index 33f3856a9c3c..4bcd8d366f38 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -856,8 +856,11 @@ __SYSCALL(__NR_watch_devices, sys_watch_devices) #define __NR_openat2 437 __SYSCALL(__NR_openat2, sys_openat2) +#define __NR_openat2 438 +__SYSCALL(__NR_process_madvise, sys_process_madvise) + #undef __NR_syscalls -#define __NR_syscalls 438 +#define __NR_syscalls 439 /* * 32 bit systems traditionally used different diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 0e9b275260f8..10ce5eac8b4b 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -281,6 +281,7 @@ COND_SYSCALL(mlockall); COND_SYSCALL(munlockall); COND_SYSCALL(mincore); COND_SYSCALL(madvise); +COND_SYSCALL(process_madvise); COND_SYSCALL(remap_file_pages); COND_SYSCALL(mbind); COND_SYSCALL_COMPAT(mbind); diff --git a/mm/madvise.c b/mm/madvise.c index 0c901de531e4..e15dfb4df7bf 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -17,6 +17,7 @@ #include <linux/falloc.h> #include <linux/fadvise.h> #include <linux/sched.h> +#include <linux/sched/mm.h> #include <linux/ksm.h> #include <linux/fs.h> #include <linux/file.h> @@ -993,6 +994,18 @@ madvise_behavior_valid(int behavior) } } +static bool +process_madvise_behavior_valid(int behavior) +{ + switch (behavior) { + case MADV_COLD: + case MADV_PAGEOUT: + return true; + default: + return false; + } +} + /* * madvise_common - request behavior hint to address range of the target process * @@ -1169,3 +1182,54 @@ SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior) { return madvise_common(current, current->mm, start, len_in, behavior); } + +SYSCALL_DEFINE5(process_madvise, int, pidfd, unsigned long, start, + size_t, len_in, int, behavior, unsigned long, flags) +{ + int ret; + struct fd f; + struct pid *pid; + struct task_struct *task; + struct mm_struct *mm; + + if (flags != 0) + return -EINVAL; + + if (!process_madvise_behavior_valid(behavior)) + return -EINVAL; + + f = fdget(pidfd); + if (!f.file) + return -EBADF; + + pid = pidfd_pid(f.file); + if (IS_ERR(pid)) { + ret = PTR_ERR(pid); + goto err; + } + + rcu_read_lock(); + task = pid_task(pid, PIDTYPE_PID); + if (!task) { + rcu_read_unlock(); + ret = -ESRCH; + goto err; + } + + get_task_struct(task); + rcu_read_unlock(); + + mm = mm_access(task, PTRACE_MODE_ATTACH_FSCREDS); + if (IS_ERR_OR_NULL(mm)) { + ret = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH; + goto release_task; + } + + ret = madvise_common(task, mm, start, len_in, behavior); + mmput(mm); +release_task: + put_task_struct(task); +err: + fdput(f); + return ret; +}
There are usecases that System Management Software(SMS) want to give a memory hint to other processes because it's not known to the application. In the case of Android, ActivityManagerService daemon manges app's life cycle and that daemon must be able to initiate reclaim on its own without any app involvement. To solve the issue, this patch introduces new syscall process_madvise(2). It uses pidfd of an external processs to give the hint. int process_madvise(int pidfd, void *addr, size_t length, int advise, unsigned long flag); Since it could affect other process's address range, only privileged process(CAP_SYS_PTRACE) or something else(e.g., being the same UID) gives it the right to ptrace the process could use it successfully. The flag argument is reserved for future use if we need to extend the API. Supporting all hints madvise has/will supported/support to process_madvise is rather risky. Because we are not sure all hints make sense from external process and implementation for the hint may rely on the caller being in the current context so it could be error-prone. Thus, I just limited hints as MADV_[COLD|PAGEOUT] in this patch. If someone want to add other hints, we could hear hear the usecase and review it for each hint. It's more safe for maintainace rather than introducing a buggy syscall but hard to fix it later. Signed-off-by: Minchan Kim <minchan@kernel.org> --- arch/alpha/kernel/syscalls/syscall.tbl | 1 + arch/arm/tools/syscall.tbl | 1 + arch/arm64/include/asm/unistd.h | 2 +- arch/arm64/include/asm/unistd32.h | 2 + arch/ia64/kernel/syscalls/syscall.tbl | 1 + arch/m68k/kernel/syscalls/syscall.tbl | 1 + arch/microblaze/kernel/syscalls/syscall.tbl | 1 + arch/mips/kernel/syscalls/syscall_n32.tbl | 1 + arch/mips/kernel/syscalls/syscall_n64.tbl | 1 + arch/parisc/kernel/syscalls/syscall.tbl | 1 + arch/powerpc/kernel/syscalls/syscall.tbl | 1 + arch/s390/kernel/syscalls/syscall.tbl | 1 + arch/sh/kernel/syscalls/syscall.tbl | 1 + arch/sparc/kernel/syscalls/syscall.tbl | 1 + arch/x86/entry/syscalls/syscall_32.tbl | 1 + arch/x86/entry/syscalls/syscall_64.tbl | 1 + arch/xtensa/kernel/syscalls/syscall.tbl | 1 + include/linux/syscalls.h | 2 + include/uapi/asm-generic/unistd.h | 5 +- kernel/sys_ni.c | 1 + mm/madvise.c | 64 +++++++++++++++++++++ 21 files changed, 89 insertions(+), 2 deletions(-)