@@ -373,6 +373,7 @@
# This one is a temporary number, designed for no clashes.
# Nothing but DTrace should use it.
473 common waitfd sys_waitfd
+474 common get_vector sys_get_vector
#
# Due to a historical design error, certain syscalls are numbered differently
@@ -92,6 +92,7 @@
#include <linux/string_helpers.h>
#include <linux/user_namespace.h>
#include <linux/fs_struct.h>
+#include <linux/syscalls.h>
#include <asm/processor.h>
#include "internal.h"
@@ -449,6 +450,89 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
return 0;
}
+/*
+ * Get the start times of the array of PIDs given in pidarr
+ * If any PID is not found or there is an error for any one of the PIDs,
+ * indicate an error by returning start time for that PID as 0, and continue
+ * to the next PID
+ */
+void pids_start_time(int *pidarr, size_t len, unsigned long long *stimes)
+{
+ struct task_struct *task = NULL;
+ int i;
+ struct pid *pid = NULL;
+
+ for (i = 0; i < len; i++) {
+ pid = find_get_pid(pidarr[i]);
+ if (!pid) {
+ stimes[i] = 0;
+ continue;
+ }
+
+ task = get_pid_task(pid, PIDTYPE_PID);
+ if (!task) {
+ stimes[i] = 0;
+ continue;
+ }
+
+ if (task->pid == pidarr[i])
+ stimes[i] =
+ nsec_to_clock_t(timens_add_boottime_ns(task->start_boottime));
+ else
+ stimes[i] = 0;
+
+ put_task_struct(task);
+ }
+}
+
+asmlinkage long sys_get_vector(int op, size_t len, const void __user *arg,
+ void *out_arr)
+{
+ size_t in_tsize, out_tsize;
+ int *in_karr;
+ unsigned long long *out_karr;
+
+ switch (op) {
+ case PID_START_TIME:
+ in_tsize = len * sizeof(int);
+ in_karr = (int *) kmalloc(in_tsize, GFP_KERNEL);
+ if (!in_karr)
+ return -ENOMEM;
+
+ if (copy_from_user(in_karr, arg, in_tsize)) {
+ goto free_in_karr;
+ return -EFAULT;
+ }
+
+ out_tsize = len * sizeof(unsigned long long);
+ out_karr = (unsigned long long *) kmalloc(out_tsize, GFP_KERNEL);
+ if (!out_karr) {
+ goto free_in_karr;
+ return -ENOMEM;
+ }
+
+ pids_start_time(in_karr, len, out_karr);
+ if (copy_to_user(out_arr, out_karr, out_tsize)) {
+ goto free_out_karr;
+ return -EFAULT;
+ }
+free_out_karr:
+ kfree(out_karr);
+free_in_karr:
+ kfree(in_karr);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+SYSCALL_DEFINE4(get_vector, int, op, size_t, len, const void __user *, arg,
+ void *, out_arr)
+{
+ return sys_get_vector(op, len, arg, out_arr);
+}
+
static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task, int whole)
{
@@ -74,6 +74,8 @@ struct proc_dir_entry {
0)
#define SIZEOF_PDE_INLINE_NAME (SIZEOF_PDE - sizeof(struct proc_dir_entry))
+#define PID_START_TIME 1
+
static inline bool pde_is_permanent(const struct proc_dir_entry *pde)
{
return pde->flags & PROC_ENTRY_PERMANENT;
@@ -1384,4 +1384,6 @@ int __sys_getsockopt(int fd, int level, int optname, char __user *optval,
int __user *optlen);
int __sys_setsockopt(int fd, int level, int optname, char __user *optval,
int optlen);
+asmlinkage long sys_get_vector(int op, size_t len, const void __user *arg,
+ void *outp);
#endif
@@ -883,8 +883,11 @@ __SYSCALL(__NR_process_mrelease, sys_process_mrelease)
#define __NR_waitfd 473
__SYSCALL(__NR_waitfd, sys_waitfd)
+#define __NR_get_vector 474
+__SYSCALL(__NR_get_vector, sys_get_vector)
+
#undef __NR_syscalls
-#define __NR_syscalls 474
+#define __NR_syscalls 475
/*
* 32 bit systems traditionally used different
@@ -478,3 +478,4 @@ COND_SYSCALL(setuid16);
/* restartable sequence */
COND_SYSCALL(rseq);
+COND_SYSCALL(get_vector);