162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * This file contains the procedures for the handling of select and poll
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Created for Linux based loosely upon Mathius Lattner's minix
662306a36Sopenharmony_ci * patches by Peter MacDonald. Heavily edited by Linus.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci *  4 February 1994
962306a36Sopenharmony_ci *     COFF/ELF binary emulation. If the process has the STICKY_TIMEOUTS
1062306a36Sopenharmony_ci *     flag set in its personality we do *not* modify the given timeout
1162306a36Sopenharmony_ci *     parameter to reflect time remaining.
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci *  24 January 2000
1462306a36Sopenharmony_ci *     Changed sys_poll()/do_poll() to use PAGE_SIZE chunk-based allocation
1562306a36Sopenharmony_ci *     of fds to overcome nfds < 16390 descriptors limit (Tigran Aivazian).
1662306a36Sopenharmony_ci */
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include <linux/compat.h>
1962306a36Sopenharmony_ci#include <linux/kernel.h>
2062306a36Sopenharmony_ci#include <linux/sched/signal.h>
2162306a36Sopenharmony_ci#include <linux/sched/rt.h>
2262306a36Sopenharmony_ci#include <linux/syscalls.h>
2362306a36Sopenharmony_ci#include <linux/export.h>
2462306a36Sopenharmony_ci#include <linux/slab.h>
2562306a36Sopenharmony_ci#include <linux/poll.h>
2662306a36Sopenharmony_ci#include <linux/personality.h> /* for STICKY_TIMEOUTS */
2762306a36Sopenharmony_ci#include <linux/file.h>
2862306a36Sopenharmony_ci#include <linux/fdtable.h>
2962306a36Sopenharmony_ci#include <linux/fs.h>
3062306a36Sopenharmony_ci#include <linux/rcupdate.h>
3162306a36Sopenharmony_ci#include <linux/hrtimer.h>
3262306a36Sopenharmony_ci#include <linux/freezer.h>
3362306a36Sopenharmony_ci#include <net/busy_poll.h>
3462306a36Sopenharmony_ci#include <linux/vmalloc.h>
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#include <linux/uaccess.h>
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci/*
4062306a36Sopenharmony_ci * Estimate expected accuracy in ns from a timeval.
4162306a36Sopenharmony_ci *
4262306a36Sopenharmony_ci * After quite a bit of churning around, we've settled on
4362306a36Sopenharmony_ci * a simple thing of taking 0.1% of the timeout as the
4462306a36Sopenharmony_ci * slack, with a cap of 100 msec.
4562306a36Sopenharmony_ci * "nice" tasks get a 0.5% slack instead.
4662306a36Sopenharmony_ci *
4762306a36Sopenharmony_ci * Consider this comment an open invitation to come up with even
4862306a36Sopenharmony_ci * better solutions..
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci#define MAX_SLACK	(100 * NSEC_PER_MSEC)
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_cistatic long __estimate_accuracy(struct timespec64 *tv)
5462306a36Sopenharmony_ci{
5562306a36Sopenharmony_ci	long slack;
5662306a36Sopenharmony_ci	int divfactor = 1000;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	if (tv->tv_sec < 0)
5962306a36Sopenharmony_ci		return 0;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	if (task_nice(current) > 0)
6262306a36Sopenharmony_ci		divfactor = divfactor / 5;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	if (tv->tv_sec > MAX_SLACK / (NSEC_PER_SEC/divfactor))
6562306a36Sopenharmony_ci		return MAX_SLACK;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	slack = tv->tv_nsec / divfactor;
6862306a36Sopenharmony_ci	slack += tv->tv_sec * (NSEC_PER_SEC/divfactor);
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	if (slack > MAX_SLACK)
7162306a36Sopenharmony_ci		return MAX_SLACK;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	return slack;
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ciu64 select_estimate_accuracy(struct timespec64 *tv)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	u64 ret;
7962306a36Sopenharmony_ci	struct timespec64 now;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	/*
8262306a36Sopenharmony_ci	 * Realtime tasks get a slack of 0 for obvious reasons.
8362306a36Sopenharmony_ci	 */
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	if (rt_task(current))
8662306a36Sopenharmony_ci		return 0;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	ktime_get_ts64(&now);
8962306a36Sopenharmony_ci	now = timespec64_sub(*tv, now);
9062306a36Sopenharmony_ci	ret = __estimate_accuracy(&now);
9162306a36Sopenharmony_ci	if (ret < current->timer_slack_ns)
9262306a36Sopenharmony_ci		return current->timer_slack_ns;
9362306a36Sopenharmony_ci	return ret;
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistruct poll_table_page {
9962306a36Sopenharmony_ci	struct poll_table_page * next;
10062306a36Sopenharmony_ci	struct poll_table_entry * entry;
10162306a36Sopenharmony_ci	struct poll_table_entry entries[];
10262306a36Sopenharmony_ci};
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci#define POLL_TABLE_FULL(table) \
10562306a36Sopenharmony_ci	((unsigned long)((table)->entry+1) > PAGE_SIZE + (unsigned long)(table))
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci/*
10862306a36Sopenharmony_ci * Ok, Peter made a complicated, but straightforward multiple_wait() function.
10962306a36Sopenharmony_ci * I have rewritten this, taking some shortcuts: This code may not be easy to
11062306a36Sopenharmony_ci * follow, but it should be free of race-conditions, and it's practical. If you
11162306a36Sopenharmony_ci * understand what I'm doing here, then you understand how the linux
11262306a36Sopenharmony_ci * sleep/wakeup mechanism works.
11362306a36Sopenharmony_ci *
11462306a36Sopenharmony_ci * Two very simple procedures, poll_wait() and poll_freewait() make all the
11562306a36Sopenharmony_ci * work.  poll_wait() is an inline-function defined in <linux/poll.h>,
11662306a36Sopenharmony_ci * as all select/poll functions have to call it to add an entry to the
11762306a36Sopenharmony_ci * poll table.
11862306a36Sopenharmony_ci */
11962306a36Sopenharmony_cistatic void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
12062306a36Sopenharmony_ci		       poll_table *p);
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_civoid poll_initwait(struct poll_wqueues *pwq)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	init_poll_funcptr(&pwq->pt, __pollwait);
12562306a36Sopenharmony_ci	pwq->polling_task = current;
12662306a36Sopenharmony_ci	pwq->triggered = 0;
12762306a36Sopenharmony_ci	pwq->error = 0;
12862306a36Sopenharmony_ci	pwq->table = NULL;
12962306a36Sopenharmony_ci	pwq->inline_index = 0;
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ciEXPORT_SYMBOL(poll_initwait);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cistatic void free_poll_entry(struct poll_table_entry *entry)
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	remove_wait_queue(entry->wait_address, &entry->wait);
13662306a36Sopenharmony_ci	fput(entry->filp);
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_civoid poll_freewait(struct poll_wqueues *pwq)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	struct poll_table_page * p = pwq->table;
14262306a36Sopenharmony_ci	int i;
14362306a36Sopenharmony_ci	for (i = 0; i < pwq->inline_index; i++)
14462306a36Sopenharmony_ci		free_poll_entry(pwq->inline_entries + i);
14562306a36Sopenharmony_ci	while (p) {
14662306a36Sopenharmony_ci		struct poll_table_entry * entry;
14762306a36Sopenharmony_ci		struct poll_table_page *old;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci		entry = p->entry;
15062306a36Sopenharmony_ci		do {
15162306a36Sopenharmony_ci			entry--;
15262306a36Sopenharmony_ci			free_poll_entry(entry);
15362306a36Sopenharmony_ci		} while (entry > p->entries);
15462306a36Sopenharmony_ci		old = p;
15562306a36Sopenharmony_ci		p = p->next;
15662306a36Sopenharmony_ci		free_page((unsigned long) old);
15762306a36Sopenharmony_ci	}
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ciEXPORT_SYMBOL(poll_freewait);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic struct poll_table_entry *poll_get_entry(struct poll_wqueues *p)
16262306a36Sopenharmony_ci{
16362306a36Sopenharmony_ci	struct poll_table_page *table = p->table;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	if (p->inline_index < N_INLINE_POLL_ENTRIES)
16662306a36Sopenharmony_ci		return p->inline_entries + p->inline_index++;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	if (!table || POLL_TABLE_FULL(table)) {
16962306a36Sopenharmony_ci		struct poll_table_page *new_table;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci		new_table = (struct poll_table_page *) __get_free_page(GFP_KERNEL);
17262306a36Sopenharmony_ci		if (!new_table) {
17362306a36Sopenharmony_ci			p->error = -ENOMEM;
17462306a36Sopenharmony_ci			return NULL;
17562306a36Sopenharmony_ci		}
17662306a36Sopenharmony_ci		new_table->entry = new_table->entries;
17762306a36Sopenharmony_ci		new_table->next = table;
17862306a36Sopenharmony_ci		p->table = new_table;
17962306a36Sopenharmony_ci		table = new_table;
18062306a36Sopenharmony_ci	}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	return table->entry++;
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cistatic int __pollwake(wait_queue_entry_t *wait, unsigned mode, int sync, void *key)
18662306a36Sopenharmony_ci{
18762306a36Sopenharmony_ci	struct poll_wqueues *pwq = wait->private;
18862306a36Sopenharmony_ci	DECLARE_WAITQUEUE(dummy_wait, pwq->polling_task);
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	/*
19162306a36Sopenharmony_ci	 * Although this function is called under waitqueue lock, LOCK
19262306a36Sopenharmony_ci	 * doesn't imply write barrier and the users expect write
19362306a36Sopenharmony_ci	 * barrier semantics on wakeup functions.  The following
19462306a36Sopenharmony_ci	 * smp_wmb() is equivalent to smp_wmb() in try_to_wake_up()
19562306a36Sopenharmony_ci	 * and is paired with smp_store_mb() in poll_schedule_timeout.
19662306a36Sopenharmony_ci	 */
19762306a36Sopenharmony_ci	smp_wmb();
19862306a36Sopenharmony_ci	pwq->triggered = 1;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	/*
20162306a36Sopenharmony_ci	 * Perform the default wake up operation using a dummy
20262306a36Sopenharmony_ci	 * waitqueue.
20362306a36Sopenharmony_ci	 *
20462306a36Sopenharmony_ci	 * TODO: This is hacky but there currently is no interface to
20562306a36Sopenharmony_ci	 * pass in @sync.  @sync is scheduled to be removed and once
20662306a36Sopenharmony_ci	 * that happens, wake_up_process() can be used directly.
20762306a36Sopenharmony_ci	 */
20862306a36Sopenharmony_ci	return default_wake_function(&dummy_wait, mode, sync, key);
20962306a36Sopenharmony_ci}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_cistatic int pollwake(wait_queue_entry_t *wait, unsigned mode, int sync, void *key)
21262306a36Sopenharmony_ci{
21362306a36Sopenharmony_ci	struct poll_table_entry *entry;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	entry = container_of(wait, struct poll_table_entry, wait);
21662306a36Sopenharmony_ci	if (key && !(key_to_poll(key) & entry->key))
21762306a36Sopenharmony_ci		return 0;
21862306a36Sopenharmony_ci	return __pollwake(wait, mode, sync, key);
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci/* Add a new entry */
22262306a36Sopenharmony_cistatic void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
22362306a36Sopenharmony_ci				poll_table *p)
22462306a36Sopenharmony_ci{
22562306a36Sopenharmony_ci	struct poll_wqueues *pwq = container_of(p, struct poll_wqueues, pt);
22662306a36Sopenharmony_ci	struct poll_table_entry *entry = poll_get_entry(pwq);
22762306a36Sopenharmony_ci	if (!entry)
22862306a36Sopenharmony_ci		return;
22962306a36Sopenharmony_ci	entry->filp = get_file(filp);
23062306a36Sopenharmony_ci	entry->wait_address = wait_address;
23162306a36Sopenharmony_ci	entry->key = p->_key;
23262306a36Sopenharmony_ci	init_waitqueue_func_entry(&entry->wait, pollwake);
23362306a36Sopenharmony_ci	entry->wait.private = pwq;
23462306a36Sopenharmony_ci	add_wait_queue(wait_address, &entry->wait);
23562306a36Sopenharmony_ci}
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_cistatic int poll_schedule_timeout(struct poll_wqueues *pwq, int state,
23862306a36Sopenharmony_ci			  ktime_t *expires, unsigned long slack)
23962306a36Sopenharmony_ci{
24062306a36Sopenharmony_ci	int rc = -EINTR;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	set_current_state(state);
24362306a36Sopenharmony_ci	if (!pwq->triggered)
24462306a36Sopenharmony_ci		rc = schedule_hrtimeout_range(expires, slack, HRTIMER_MODE_ABS);
24562306a36Sopenharmony_ci	__set_current_state(TASK_RUNNING);
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	/*
24862306a36Sopenharmony_ci	 * Prepare for the next iteration.
24962306a36Sopenharmony_ci	 *
25062306a36Sopenharmony_ci	 * The following smp_store_mb() serves two purposes.  First, it's
25162306a36Sopenharmony_ci	 * the counterpart rmb of the wmb in pollwake() such that data
25262306a36Sopenharmony_ci	 * written before wake up is always visible after wake up.
25362306a36Sopenharmony_ci	 * Second, the full barrier guarantees that triggered clearing
25462306a36Sopenharmony_ci	 * doesn't pass event check of the next iteration.  Note that
25562306a36Sopenharmony_ci	 * this problem doesn't exist for the first iteration as
25662306a36Sopenharmony_ci	 * add_wait_queue() has full barrier semantics.
25762306a36Sopenharmony_ci	 */
25862306a36Sopenharmony_ci	smp_store_mb(pwq->triggered, 0);
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	return rc;
26162306a36Sopenharmony_ci}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci/**
26462306a36Sopenharmony_ci * poll_select_set_timeout - helper function to setup the timeout value
26562306a36Sopenharmony_ci * @to:		pointer to timespec64 variable for the final timeout
26662306a36Sopenharmony_ci * @sec:	seconds (from user space)
26762306a36Sopenharmony_ci * @nsec:	nanoseconds (from user space)
26862306a36Sopenharmony_ci *
26962306a36Sopenharmony_ci * Note, we do not use a timespec for the user space value here, That
27062306a36Sopenharmony_ci * way we can use the function for timeval and compat interfaces as well.
27162306a36Sopenharmony_ci *
27262306a36Sopenharmony_ci * Returns -EINVAL if sec/nsec are not normalized. Otherwise 0.
27362306a36Sopenharmony_ci */
27462306a36Sopenharmony_ciint poll_select_set_timeout(struct timespec64 *to, time64_t sec, long nsec)
27562306a36Sopenharmony_ci{
27662306a36Sopenharmony_ci	struct timespec64 ts = {.tv_sec = sec, .tv_nsec = nsec};
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	if (!timespec64_valid(&ts))
27962306a36Sopenharmony_ci		return -EINVAL;
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	/* Optimize for the zero timeout value here */
28262306a36Sopenharmony_ci	if (!sec && !nsec) {
28362306a36Sopenharmony_ci		to->tv_sec = to->tv_nsec = 0;
28462306a36Sopenharmony_ci	} else {
28562306a36Sopenharmony_ci		ktime_get_ts64(to);
28662306a36Sopenharmony_ci		*to = timespec64_add_safe(*to, ts);
28762306a36Sopenharmony_ci	}
28862306a36Sopenharmony_ci	return 0;
28962306a36Sopenharmony_ci}
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_cienum poll_time_type {
29262306a36Sopenharmony_ci	PT_TIMEVAL = 0,
29362306a36Sopenharmony_ci	PT_OLD_TIMEVAL = 1,
29462306a36Sopenharmony_ci	PT_TIMESPEC = 2,
29562306a36Sopenharmony_ci	PT_OLD_TIMESPEC = 3,
29662306a36Sopenharmony_ci};
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_cistatic int poll_select_finish(struct timespec64 *end_time,
29962306a36Sopenharmony_ci			      void __user *p,
30062306a36Sopenharmony_ci			      enum poll_time_type pt_type, int ret)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	struct timespec64 rts;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	restore_saved_sigmask_unless(ret == -ERESTARTNOHAND);
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	if (!p)
30762306a36Sopenharmony_ci		return ret;
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	if (current->personality & STICKY_TIMEOUTS)
31062306a36Sopenharmony_ci		goto sticky;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	/* No update for zero timeout */
31362306a36Sopenharmony_ci	if (!end_time->tv_sec && !end_time->tv_nsec)
31462306a36Sopenharmony_ci		return ret;
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	ktime_get_ts64(&rts);
31762306a36Sopenharmony_ci	rts = timespec64_sub(*end_time, rts);
31862306a36Sopenharmony_ci	if (rts.tv_sec < 0)
31962306a36Sopenharmony_ci		rts.tv_sec = rts.tv_nsec = 0;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	switch (pt_type) {
32362306a36Sopenharmony_ci	case PT_TIMEVAL:
32462306a36Sopenharmony_ci		{
32562306a36Sopenharmony_ci			struct __kernel_old_timeval rtv;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci			if (sizeof(rtv) > sizeof(rtv.tv_sec) + sizeof(rtv.tv_usec))
32862306a36Sopenharmony_ci				memset(&rtv, 0, sizeof(rtv));
32962306a36Sopenharmony_ci			rtv.tv_sec = rts.tv_sec;
33062306a36Sopenharmony_ci			rtv.tv_usec = rts.tv_nsec / NSEC_PER_USEC;
33162306a36Sopenharmony_ci			if (!copy_to_user(p, &rtv, sizeof(rtv)))
33262306a36Sopenharmony_ci				return ret;
33362306a36Sopenharmony_ci		}
33462306a36Sopenharmony_ci		break;
33562306a36Sopenharmony_ci	case PT_OLD_TIMEVAL:
33662306a36Sopenharmony_ci		{
33762306a36Sopenharmony_ci			struct old_timeval32 rtv;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci			rtv.tv_sec = rts.tv_sec;
34062306a36Sopenharmony_ci			rtv.tv_usec = rts.tv_nsec / NSEC_PER_USEC;
34162306a36Sopenharmony_ci			if (!copy_to_user(p, &rtv, sizeof(rtv)))
34262306a36Sopenharmony_ci				return ret;
34362306a36Sopenharmony_ci		}
34462306a36Sopenharmony_ci		break;
34562306a36Sopenharmony_ci	case PT_TIMESPEC:
34662306a36Sopenharmony_ci		if (!put_timespec64(&rts, p))
34762306a36Sopenharmony_ci			return ret;
34862306a36Sopenharmony_ci		break;
34962306a36Sopenharmony_ci	case PT_OLD_TIMESPEC:
35062306a36Sopenharmony_ci		if (!put_old_timespec32(&rts, p))
35162306a36Sopenharmony_ci			return ret;
35262306a36Sopenharmony_ci		break;
35362306a36Sopenharmony_ci	default:
35462306a36Sopenharmony_ci		BUG();
35562306a36Sopenharmony_ci	}
35662306a36Sopenharmony_ci	/*
35762306a36Sopenharmony_ci	 * If an application puts its timeval in read-only memory, we
35862306a36Sopenharmony_ci	 * don't want the Linux-specific update to the timeval to
35962306a36Sopenharmony_ci	 * cause a fault after the select has completed
36062306a36Sopenharmony_ci	 * successfully. However, because we're not updating the
36162306a36Sopenharmony_ci	 * timeval, we can't restart the system call.
36262306a36Sopenharmony_ci	 */
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_cisticky:
36562306a36Sopenharmony_ci	if (ret == -ERESTARTNOHAND)
36662306a36Sopenharmony_ci		ret = -EINTR;
36762306a36Sopenharmony_ci	return ret;
36862306a36Sopenharmony_ci}
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci/*
37162306a36Sopenharmony_ci * Scalable version of the fd_set.
37262306a36Sopenharmony_ci */
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_citypedef struct {
37562306a36Sopenharmony_ci	unsigned long *in, *out, *ex;
37662306a36Sopenharmony_ci	unsigned long *res_in, *res_out, *res_ex;
37762306a36Sopenharmony_ci} fd_set_bits;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci/*
38062306a36Sopenharmony_ci * How many longwords for "nr" bits?
38162306a36Sopenharmony_ci */
38262306a36Sopenharmony_ci#define FDS_BITPERLONG	(8*sizeof(long))
38362306a36Sopenharmony_ci#define FDS_LONGS(nr)	(((nr)+FDS_BITPERLONG-1)/FDS_BITPERLONG)
38462306a36Sopenharmony_ci#define FDS_BYTES(nr)	(FDS_LONGS(nr)*sizeof(long))
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci/*
38762306a36Sopenharmony_ci * Use "unsigned long" accesses to let user-mode fd_set's be long-aligned.
38862306a36Sopenharmony_ci */
38962306a36Sopenharmony_cistatic inline
39062306a36Sopenharmony_ciint get_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset)
39162306a36Sopenharmony_ci{
39262306a36Sopenharmony_ci	nr = FDS_BYTES(nr);
39362306a36Sopenharmony_ci	if (ufdset)
39462306a36Sopenharmony_ci		return copy_from_user(fdset, ufdset, nr) ? -EFAULT : 0;
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	memset(fdset, 0, nr);
39762306a36Sopenharmony_ci	return 0;
39862306a36Sopenharmony_ci}
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_cistatic inline unsigned long __must_check
40162306a36Sopenharmony_ciset_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset)
40262306a36Sopenharmony_ci{
40362306a36Sopenharmony_ci	if (ufdset)
40462306a36Sopenharmony_ci		return __copy_to_user(ufdset, fdset, FDS_BYTES(nr));
40562306a36Sopenharmony_ci	return 0;
40662306a36Sopenharmony_ci}
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_cistatic inline
40962306a36Sopenharmony_civoid zero_fd_set(unsigned long nr, unsigned long *fdset)
41062306a36Sopenharmony_ci{
41162306a36Sopenharmony_ci	memset(fdset, 0, FDS_BYTES(nr));
41262306a36Sopenharmony_ci}
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci#define FDS_IN(fds, n)		(fds->in + n)
41562306a36Sopenharmony_ci#define FDS_OUT(fds, n)		(fds->out + n)
41662306a36Sopenharmony_ci#define FDS_EX(fds, n)		(fds->ex + n)
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci#define BITS(fds, n)	(*FDS_IN(fds, n)|*FDS_OUT(fds, n)|*FDS_EX(fds, n))
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_cistatic int max_select_fd(unsigned long n, fd_set_bits *fds)
42162306a36Sopenharmony_ci{
42262306a36Sopenharmony_ci	unsigned long *open_fds;
42362306a36Sopenharmony_ci	unsigned long set;
42462306a36Sopenharmony_ci	int max;
42562306a36Sopenharmony_ci	struct fdtable *fdt;
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	/* handle last in-complete long-word first */
42862306a36Sopenharmony_ci	set = ~(~0UL << (n & (BITS_PER_LONG-1)));
42962306a36Sopenharmony_ci	n /= BITS_PER_LONG;
43062306a36Sopenharmony_ci	fdt = files_fdtable(current->files);
43162306a36Sopenharmony_ci	open_fds = fdt->open_fds + n;
43262306a36Sopenharmony_ci	max = 0;
43362306a36Sopenharmony_ci	if (set) {
43462306a36Sopenharmony_ci		set &= BITS(fds, n);
43562306a36Sopenharmony_ci		if (set) {
43662306a36Sopenharmony_ci			if (!(set & ~*open_fds))
43762306a36Sopenharmony_ci				goto get_max;
43862306a36Sopenharmony_ci			return -EBADF;
43962306a36Sopenharmony_ci		}
44062306a36Sopenharmony_ci	}
44162306a36Sopenharmony_ci	while (n) {
44262306a36Sopenharmony_ci		open_fds--;
44362306a36Sopenharmony_ci		n--;
44462306a36Sopenharmony_ci		set = BITS(fds, n);
44562306a36Sopenharmony_ci		if (!set)
44662306a36Sopenharmony_ci			continue;
44762306a36Sopenharmony_ci		if (set & ~*open_fds)
44862306a36Sopenharmony_ci			return -EBADF;
44962306a36Sopenharmony_ci		if (max)
45062306a36Sopenharmony_ci			continue;
45162306a36Sopenharmony_ciget_max:
45262306a36Sopenharmony_ci		do {
45362306a36Sopenharmony_ci			max++;
45462306a36Sopenharmony_ci			set >>= 1;
45562306a36Sopenharmony_ci		} while (set);
45662306a36Sopenharmony_ci		max += n * BITS_PER_LONG;
45762306a36Sopenharmony_ci	}
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	return max;
46062306a36Sopenharmony_ci}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci#define POLLIN_SET (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN | EPOLLHUP | EPOLLERR |\
46362306a36Sopenharmony_ci			EPOLLNVAL)
46462306a36Sopenharmony_ci#define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT | EPOLLERR |\
46562306a36Sopenharmony_ci			 EPOLLNVAL)
46662306a36Sopenharmony_ci#define POLLEX_SET (EPOLLPRI | EPOLLNVAL)
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_cistatic inline void wait_key_set(poll_table *wait, unsigned long in,
46962306a36Sopenharmony_ci				unsigned long out, unsigned long bit,
47062306a36Sopenharmony_ci				__poll_t ll_flag)
47162306a36Sopenharmony_ci{
47262306a36Sopenharmony_ci	wait->_key = POLLEX_SET | ll_flag;
47362306a36Sopenharmony_ci	if (in & bit)
47462306a36Sopenharmony_ci		wait->_key |= POLLIN_SET;
47562306a36Sopenharmony_ci	if (out & bit)
47662306a36Sopenharmony_ci		wait->_key |= POLLOUT_SET;
47762306a36Sopenharmony_ci}
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_cistatic noinline_for_stack int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time)
48062306a36Sopenharmony_ci{
48162306a36Sopenharmony_ci	ktime_t expire, *to = NULL;
48262306a36Sopenharmony_ci	struct poll_wqueues table;
48362306a36Sopenharmony_ci	poll_table *wait;
48462306a36Sopenharmony_ci	int retval, i, timed_out = 0;
48562306a36Sopenharmony_ci	u64 slack = 0;
48662306a36Sopenharmony_ci	__poll_t busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0;
48762306a36Sopenharmony_ci	unsigned long busy_start = 0;
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	rcu_read_lock();
49062306a36Sopenharmony_ci	retval = max_select_fd(n, fds);
49162306a36Sopenharmony_ci	rcu_read_unlock();
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	if (retval < 0)
49462306a36Sopenharmony_ci		return retval;
49562306a36Sopenharmony_ci	n = retval;
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	poll_initwait(&table);
49862306a36Sopenharmony_ci	wait = &table.pt;
49962306a36Sopenharmony_ci	if (end_time && !end_time->tv_sec && !end_time->tv_nsec) {
50062306a36Sopenharmony_ci		wait->_qproc = NULL;
50162306a36Sopenharmony_ci		timed_out = 1;
50262306a36Sopenharmony_ci	}
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	if (end_time && !timed_out)
50562306a36Sopenharmony_ci		slack = select_estimate_accuracy(end_time);
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	retval = 0;
50862306a36Sopenharmony_ci	for (;;) {
50962306a36Sopenharmony_ci		unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;
51062306a36Sopenharmony_ci		bool can_busy_loop = false;
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci		inp = fds->in; outp = fds->out; exp = fds->ex;
51362306a36Sopenharmony_ci		rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci		for (i = 0; i < n; ++rinp, ++routp, ++rexp) {
51662306a36Sopenharmony_ci			unsigned long in, out, ex, all_bits, bit = 1, j;
51762306a36Sopenharmony_ci			unsigned long res_in = 0, res_out = 0, res_ex = 0;
51862306a36Sopenharmony_ci			__poll_t mask;
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci			in = *inp++; out = *outp++; ex = *exp++;
52162306a36Sopenharmony_ci			all_bits = in | out | ex;
52262306a36Sopenharmony_ci			if (all_bits == 0) {
52362306a36Sopenharmony_ci				i += BITS_PER_LONG;
52462306a36Sopenharmony_ci				continue;
52562306a36Sopenharmony_ci			}
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci			for (j = 0; j < BITS_PER_LONG; ++j, ++i, bit <<= 1) {
52862306a36Sopenharmony_ci				struct fd f;
52962306a36Sopenharmony_ci				if (i >= n)
53062306a36Sopenharmony_ci					break;
53162306a36Sopenharmony_ci				if (!(bit & all_bits))
53262306a36Sopenharmony_ci					continue;
53362306a36Sopenharmony_ci				mask = EPOLLNVAL;
53462306a36Sopenharmony_ci				f = fdget(i);
53562306a36Sopenharmony_ci				if (f.file) {
53662306a36Sopenharmony_ci					wait_key_set(wait, in, out, bit,
53762306a36Sopenharmony_ci						     busy_flag);
53862306a36Sopenharmony_ci					mask = vfs_poll(f.file, wait);
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci					fdput(f);
54162306a36Sopenharmony_ci				}
54262306a36Sopenharmony_ci				if ((mask & POLLIN_SET) && (in & bit)) {
54362306a36Sopenharmony_ci					res_in |= bit;
54462306a36Sopenharmony_ci					retval++;
54562306a36Sopenharmony_ci					wait->_qproc = NULL;
54662306a36Sopenharmony_ci				}
54762306a36Sopenharmony_ci				if ((mask & POLLOUT_SET) && (out & bit)) {
54862306a36Sopenharmony_ci					res_out |= bit;
54962306a36Sopenharmony_ci					retval++;
55062306a36Sopenharmony_ci					wait->_qproc = NULL;
55162306a36Sopenharmony_ci				}
55262306a36Sopenharmony_ci				if ((mask & POLLEX_SET) && (ex & bit)) {
55362306a36Sopenharmony_ci					res_ex |= bit;
55462306a36Sopenharmony_ci					retval++;
55562306a36Sopenharmony_ci					wait->_qproc = NULL;
55662306a36Sopenharmony_ci				}
55762306a36Sopenharmony_ci				/* got something, stop busy polling */
55862306a36Sopenharmony_ci				if (retval) {
55962306a36Sopenharmony_ci					can_busy_loop = false;
56062306a36Sopenharmony_ci					busy_flag = 0;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci				/*
56362306a36Sopenharmony_ci				 * only remember a returned
56462306a36Sopenharmony_ci				 * POLL_BUSY_LOOP if we asked for it
56562306a36Sopenharmony_ci				 */
56662306a36Sopenharmony_ci				} else if (busy_flag & mask)
56762306a36Sopenharmony_ci					can_busy_loop = true;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci			}
57062306a36Sopenharmony_ci			if (res_in)
57162306a36Sopenharmony_ci				*rinp = res_in;
57262306a36Sopenharmony_ci			if (res_out)
57362306a36Sopenharmony_ci				*routp = res_out;
57462306a36Sopenharmony_ci			if (res_ex)
57562306a36Sopenharmony_ci				*rexp = res_ex;
57662306a36Sopenharmony_ci			cond_resched();
57762306a36Sopenharmony_ci		}
57862306a36Sopenharmony_ci		wait->_qproc = NULL;
57962306a36Sopenharmony_ci		if (retval || timed_out || signal_pending(current))
58062306a36Sopenharmony_ci			break;
58162306a36Sopenharmony_ci		if (table.error) {
58262306a36Sopenharmony_ci			retval = table.error;
58362306a36Sopenharmony_ci			break;
58462306a36Sopenharmony_ci		}
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci		/* only if found POLL_BUSY_LOOP sockets && not out of time */
58762306a36Sopenharmony_ci		if (can_busy_loop && !need_resched()) {
58862306a36Sopenharmony_ci			if (!busy_start) {
58962306a36Sopenharmony_ci				busy_start = busy_loop_current_time();
59062306a36Sopenharmony_ci				continue;
59162306a36Sopenharmony_ci			}
59262306a36Sopenharmony_ci			if (!busy_loop_timeout(busy_start))
59362306a36Sopenharmony_ci				continue;
59462306a36Sopenharmony_ci		}
59562306a36Sopenharmony_ci		busy_flag = 0;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci		/*
59862306a36Sopenharmony_ci		 * If this is the first loop and we have a timeout
59962306a36Sopenharmony_ci		 * given, then we convert to ktime_t and set the to
60062306a36Sopenharmony_ci		 * pointer to the expiry value.
60162306a36Sopenharmony_ci		 */
60262306a36Sopenharmony_ci		if (end_time && !to) {
60362306a36Sopenharmony_ci			expire = timespec64_to_ktime(*end_time);
60462306a36Sopenharmony_ci			to = &expire;
60562306a36Sopenharmony_ci		}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci		if (!poll_schedule_timeout(&table, TASK_INTERRUPTIBLE,
60862306a36Sopenharmony_ci					   to, slack))
60962306a36Sopenharmony_ci			timed_out = 1;
61062306a36Sopenharmony_ci	}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci	poll_freewait(&table);
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	return retval;
61562306a36Sopenharmony_ci}
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci/*
61862306a36Sopenharmony_ci * We can actually return ERESTARTSYS instead of EINTR, but I'd
61962306a36Sopenharmony_ci * like to be certain this leads to no problems. So I return
62062306a36Sopenharmony_ci * EINTR just for safety.
62162306a36Sopenharmony_ci *
62262306a36Sopenharmony_ci * Update: ERESTARTSYS breaks at least the xview clock binary, so
62362306a36Sopenharmony_ci * I'm trying ERESTARTNOHAND which restart only when you want to.
62462306a36Sopenharmony_ci */
62562306a36Sopenharmony_ciint core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
62662306a36Sopenharmony_ci			   fd_set __user *exp, struct timespec64 *end_time)
62762306a36Sopenharmony_ci{
62862306a36Sopenharmony_ci	fd_set_bits fds;
62962306a36Sopenharmony_ci	void *bits;
63062306a36Sopenharmony_ci	int ret, max_fds;
63162306a36Sopenharmony_ci	size_t size, alloc_size;
63262306a36Sopenharmony_ci	struct fdtable *fdt;
63362306a36Sopenharmony_ci	/* Allocate small arguments on the stack to save memory and be faster */
63462306a36Sopenharmony_ci	long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	ret = -EINVAL;
63762306a36Sopenharmony_ci	if (n < 0)
63862306a36Sopenharmony_ci		goto out_nofds;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	/* max_fds can increase, so grab it once to avoid race */
64162306a36Sopenharmony_ci	rcu_read_lock();
64262306a36Sopenharmony_ci	fdt = files_fdtable(current->files);
64362306a36Sopenharmony_ci	max_fds = fdt->max_fds;
64462306a36Sopenharmony_ci	rcu_read_unlock();
64562306a36Sopenharmony_ci	if (n > max_fds)
64662306a36Sopenharmony_ci		n = max_fds;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	/*
64962306a36Sopenharmony_ci	 * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
65062306a36Sopenharmony_ci	 * since we used fdset we need to allocate memory in units of
65162306a36Sopenharmony_ci	 * long-words.
65262306a36Sopenharmony_ci	 */
65362306a36Sopenharmony_ci	size = FDS_BYTES(n);
65462306a36Sopenharmony_ci	bits = stack_fds;
65562306a36Sopenharmony_ci	if (size > sizeof(stack_fds) / 6) {
65662306a36Sopenharmony_ci		/* Not enough space in on-stack array; must use kmalloc */
65762306a36Sopenharmony_ci		ret = -ENOMEM;
65862306a36Sopenharmony_ci		if (size > (SIZE_MAX / 6))
65962306a36Sopenharmony_ci			goto out_nofds;
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci		alloc_size = 6 * size;
66262306a36Sopenharmony_ci		bits = kvmalloc(alloc_size, GFP_KERNEL);
66362306a36Sopenharmony_ci		if (!bits)
66462306a36Sopenharmony_ci			goto out_nofds;
66562306a36Sopenharmony_ci	}
66662306a36Sopenharmony_ci	fds.in      = bits;
66762306a36Sopenharmony_ci	fds.out     = bits +   size;
66862306a36Sopenharmony_ci	fds.ex      = bits + 2*size;
66962306a36Sopenharmony_ci	fds.res_in  = bits + 3*size;
67062306a36Sopenharmony_ci	fds.res_out = bits + 4*size;
67162306a36Sopenharmony_ci	fds.res_ex  = bits + 5*size;
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci	if ((ret = get_fd_set(n, inp, fds.in)) ||
67462306a36Sopenharmony_ci	    (ret = get_fd_set(n, outp, fds.out)) ||
67562306a36Sopenharmony_ci	    (ret = get_fd_set(n, exp, fds.ex)))
67662306a36Sopenharmony_ci		goto out;
67762306a36Sopenharmony_ci	zero_fd_set(n, fds.res_in);
67862306a36Sopenharmony_ci	zero_fd_set(n, fds.res_out);
67962306a36Sopenharmony_ci	zero_fd_set(n, fds.res_ex);
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	ret = do_select(n, &fds, end_time);
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	if (ret < 0)
68462306a36Sopenharmony_ci		goto out;
68562306a36Sopenharmony_ci	if (!ret) {
68662306a36Sopenharmony_ci		ret = -ERESTARTNOHAND;
68762306a36Sopenharmony_ci		if (signal_pending(current))
68862306a36Sopenharmony_ci			goto out;
68962306a36Sopenharmony_ci		ret = 0;
69062306a36Sopenharmony_ci	}
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_ci	if (set_fd_set(n, inp, fds.res_in) ||
69362306a36Sopenharmony_ci	    set_fd_set(n, outp, fds.res_out) ||
69462306a36Sopenharmony_ci	    set_fd_set(n, exp, fds.res_ex))
69562306a36Sopenharmony_ci		ret = -EFAULT;
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ciout:
69862306a36Sopenharmony_ci	if (bits != stack_fds)
69962306a36Sopenharmony_ci		kvfree(bits);
70062306a36Sopenharmony_ciout_nofds:
70162306a36Sopenharmony_ci	return ret;
70262306a36Sopenharmony_ci}
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_cistatic int kern_select(int n, fd_set __user *inp, fd_set __user *outp,
70562306a36Sopenharmony_ci		       fd_set __user *exp, struct __kernel_old_timeval __user *tvp)
70662306a36Sopenharmony_ci{
70762306a36Sopenharmony_ci	struct timespec64 end_time, *to = NULL;
70862306a36Sopenharmony_ci	struct __kernel_old_timeval tv;
70962306a36Sopenharmony_ci	int ret;
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci	if (tvp) {
71262306a36Sopenharmony_ci		if (copy_from_user(&tv, tvp, sizeof(tv)))
71362306a36Sopenharmony_ci			return -EFAULT;
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci		to = &end_time;
71662306a36Sopenharmony_ci		if (poll_select_set_timeout(to,
71762306a36Sopenharmony_ci				tv.tv_sec + (tv.tv_usec / USEC_PER_SEC),
71862306a36Sopenharmony_ci				(tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC))
71962306a36Sopenharmony_ci			return -EINVAL;
72062306a36Sopenharmony_ci	}
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	ret = core_sys_select(n, inp, outp, exp, to);
72362306a36Sopenharmony_ci	return poll_select_finish(&end_time, tvp, PT_TIMEVAL, ret);
72462306a36Sopenharmony_ci}
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ciSYSCALL_DEFINE5(select, int, n, fd_set __user *, inp, fd_set __user *, outp,
72762306a36Sopenharmony_ci		fd_set __user *, exp, struct __kernel_old_timeval __user *, tvp)
72862306a36Sopenharmony_ci{
72962306a36Sopenharmony_ci	return kern_select(n, inp, outp, exp, tvp);
73062306a36Sopenharmony_ci}
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_cistatic long do_pselect(int n, fd_set __user *inp, fd_set __user *outp,
73362306a36Sopenharmony_ci		       fd_set __user *exp, void __user *tsp,
73462306a36Sopenharmony_ci		       const sigset_t __user *sigmask, size_t sigsetsize,
73562306a36Sopenharmony_ci		       enum poll_time_type type)
73662306a36Sopenharmony_ci{
73762306a36Sopenharmony_ci	struct timespec64 ts, end_time, *to = NULL;
73862306a36Sopenharmony_ci	int ret;
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	if (tsp) {
74162306a36Sopenharmony_ci		switch (type) {
74262306a36Sopenharmony_ci		case PT_TIMESPEC:
74362306a36Sopenharmony_ci			if (get_timespec64(&ts, tsp))
74462306a36Sopenharmony_ci				return -EFAULT;
74562306a36Sopenharmony_ci			break;
74662306a36Sopenharmony_ci		case PT_OLD_TIMESPEC:
74762306a36Sopenharmony_ci			if (get_old_timespec32(&ts, tsp))
74862306a36Sopenharmony_ci				return -EFAULT;
74962306a36Sopenharmony_ci			break;
75062306a36Sopenharmony_ci		default:
75162306a36Sopenharmony_ci			BUG();
75262306a36Sopenharmony_ci		}
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_ci		to = &end_time;
75562306a36Sopenharmony_ci		if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
75662306a36Sopenharmony_ci			return -EINVAL;
75762306a36Sopenharmony_ci	}
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci	ret = set_user_sigmask(sigmask, sigsetsize);
76062306a36Sopenharmony_ci	if (ret)
76162306a36Sopenharmony_ci		return ret;
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci	ret = core_sys_select(n, inp, outp, exp, to);
76462306a36Sopenharmony_ci	return poll_select_finish(&end_time, tsp, type, ret);
76562306a36Sopenharmony_ci}
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci/*
76862306a36Sopenharmony_ci * Most architectures can't handle 7-argument syscalls. So we provide a
76962306a36Sopenharmony_ci * 6-argument version where the sixth argument is a pointer to a structure
77062306a36Sopenharmony_ci * which has a pointer to the sigset_t itself followed by a size_t containing
77162306a36Sopenharmony_ci * the sigset size.
77262306a36Sopenharmony_ci */
77362306a36Sopenharmony_cistruct sigset_argpack {
77462306a36Sopenharmony_ci	sigset_t __user *p;
77562306a36Sopenharmony_ci	size_t size;
77662306a36Sopenharmony_ci};
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_cistatic inline int get_sigset_argpack(struct sigset_argpack *to,
77962306a36Sopenharmony_ci				     struct sigset_argpack __user *from)
78062306a36Sopenharmony_ci{
78162306a36Sopenharmony_ci	// the path is hot enough for overhead of copy_from_user() to matter
78262306a36Sopenharmony_ci	if (from) {
78362306a36Sopenharmony_ci		if (!user_read_access_begin(from, sizeof(*from)))
78462306a36Sopenharmony_ci			return -EFAULT;
78562306a36Sopenharmony_ci		unsafe_get_user(to->p, &from->p, Efault);
78662306a36Sopenharmony_ci		unsafe_get_user(to->size, &from->size, Efault);
78762306a36Sopenharmony_ci		user_read_access_end();
78862306a36Sopenharmony_ci	}
78962306a36Sopenharmony_ci	return 0;
79062306a36Sopenharmony_ciEfault:
79162306a36Sopenharmony_ci	user_access_end();
79262306a36Sopenharmony_ci	return -EFAULT;
79362306a36Sopenharmony_ci}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ciSYSCALL_DEFINE6(pselect6, int, n, fd_set __user *, inp, fd_set __user *, outp,
79662306a36Sopenharmony_ci		fd_set __user *, exp, struct __kernel_timespec __user *, tsp,
79762306a36Sopenharmony_ci		void __user *, sig)
79862306a36Sopenharmony_ci{
79962306a36Sopenharmony_ci	struct sigset_argpack x = {NULL, 0};
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci	if (get_sigset_argpack(&x, sig))
80262306a36Sopenharmony_ci		return -EFAULT;
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci	return do_pselect(n, inp, outp, exp, tsp, x.p, x.size, PT_TIMESPEC);
80562306a36Sopenharmony_ci}
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci#if defined(CONFIG_COMPAT_32BIT_TIME) && !defined(CONFIG_64BIT)
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ciSYSCALL_DEFINE6(pselect6_time32, int, n, fd_set __user *, inp, fd_set __user *, outp,
81062306a36Sopenharmony_ci		fd_set __user *, exp, struct old_timespec32 __user *, tsp,
81162306a36Sopenharmony_ci		void __user *, sig)
81262306a36Sopenharmony_ci{
81362306a36Sopenharmony_ci	struct sigset_argpack x = {NULL, 0};
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_ci	if (get_sigset_argpack(&x, sig))
81662306a36Sopenharmony_ci		return -EFAULT;
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci	return do_pselect(n, inp, outp, exp, tsp, x.p, x.size, PT_OLD_TIMESPEC);
81962306a36Sopenharmony_ci}
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci#endif
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci#ifdef __ARCH_WANT_SYS_OLD_SELECT
82462306a36Sopenharmony_cistruct sel_arg_struct {
82562306a36Sopenharmony_ci	unsigned long n;
82662306a36Sopenharmony_ci	fd_set __user *inp, *outp, *exp;
82762306a36Sopenharmony_ci	struct __kernel_old_timeval __user *tvp;
82862306a36Sopenharmony_ci};
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ciSYSCALL_DEFINE1(old_select, struct sel_arg_struct __user *, arg)
83162306a36Sopenharmony_ci{
83262306a36Sopenharmony_ci	struct sel_arg_struct a;
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	if (copy_from_user(&a, arg, sizeof(a)))
83562306a36Sopenharmony_ci		return -EFAULT;
83662306a36Sopenharmony_ci	return kern_select(a.n, a.inp, a.outp, a.exp, a.tvp);
83762306a36Sopenharmony_ci}
83862306a36Sopenharmony_ci#endif
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_cistruct poll_list {
84162306a36Sopenharmony_ci	struct poll_list *next;
84262306a36Sopenharmony_ci	int len;
84362306a36Sopenharmony_ci	struct pollfd entries[];
84462306a36Sopenharmony_ci};
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci#define POLLFD_PER_PAGE  ((PAGE_SIZE-sizeof(struct poll_list)) / sizeof(struct pollfd))
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci/*
84962306a36Sopenharmony_ci * Fish for pollable events on the pollfd->fd file descriptor. We're only
85062306a36Sopenharmony_ci * interested in events matching the pollfd->events mask, and the result
85162306a36Sopenharmony_ci * matching that mask is both recorded in pollfd->revents and returned. The
85262306a36Sopenharmony_ci * pwait poll_table will be used by the fd-provided poll handler for waiting,
85362306a36Sopenharmony_ci * if pwait->_qproc is non-NULL.
85462306a36Sopenharmony_ci */
85562306a36Sopenharmony_cistatic inline __poll_t do_pollfd(struct pollfd *pollfd, poll_table *pwait,
85662306a36Sopenharmony_ci				     bool *can_busy_poll,
85762306a36Sopenharmony_ci				     __poll_t busy_flag)
85862306a36Sopenharmony_ci{
85962306a36Sopenharmony_ci	int fd = pollfd->fd;
86062306a36Sopenharmony_ci	__poll_t mask = 0, filter;
86162306a36Sopenharmony_ci	struct fd f;
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci	if (fd < 0)
86462306a36Sopenharmony_ci		goto out;
86562306a36Sopenharmony_ci	mask = EPOLLNVAL;
86662306a36Sopenharmony_ci	f = fdget(fd);
86762306a36Sopenharmony_ci	if (!f.file)
86862306a36Sopenharmony_ci		goto out;
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci	/* userland u16 ->events contains POLL... bitmap */
87162306a36Sopenharmony_ci	filter = demangle_poll(pollfd->events) | EPOLLERR | EPOLLHUP;
87262306a36Sopenharmony_ci	pwait->_key = filter | busy_flag;
87362306a36Sopenharmony_ci	mask = vfs_poll(f.file, pwait);
87462306a36Sopenharmony_ci	if (mask & busy_flag)
87562306a36Sopenharmony_ci		*can_busy_poll = true;
87662306a36Sopenharmony_ci	mask &= filter;		/* Mask out unneeded events. */
87762306a36Sopenharmony_ci	fdput(f);
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ciout:
88062306a36Sopenharmony_ci	/* ... and so does ->revents */
88162306a36Sopenharmony_ci	pollfd->revents = mangle_poll(mask);
88262306a36Sopenharmony_ci	return mask;
88362306a36Sopenharmony_ci}
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_cistatic int do_poll(struct poll_list *list, struct poll_wqueues *wait,
88662306a36Sopenharmony_ci		   struct timespec64 *end_time)
88762306a36Sopenharmony_ci{
88862306a36Sopenharmony_ci	poll_table* pt = &wait->pt;
88962306a36Sopenharmony_ci	ktime_t expire, *to = NULL;
89062306a36Sopenharmony_ci	int timed_out = 0, count = 0;
89162306a36Sopenharmony_ci	u64 slack = 0;
89262306a36Sopenharmony_ci	__poll_t busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0;
89362306a36Sopenharmony_ci	unsigned long busy_start = 0;
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	/* Optimise the no-wait case */
89662306a36Sopenharmony_ci	if (end_time && !end_time->tv_sec && !end_time->tv_nsec) {
89762306a36Sopenharmony_ci		pt->_qproc = NULL;
89862306a36Sopenharmony_ci		timed_out = 1;
89962306a36Sopenharmony_ci	}
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	if (end_time && !timed_out)
90262306a36Sopenharmony_ci		slack = select_estimate_accuracy(end_time);
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci	for (;;) {
90562306a36Sopenharmony_ci		struct poll_list *walk;
90662306a36Sopenharmony_ci		bool can_busy_loop = false;
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_ci		for (walk = list; walk != NULL; walk = walk->next) {
90962306a36Sopenharmony_ci			struct pollfd * pfd, * pfd_end;
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci			pfd = walk->entries;
91262306a36Sopenharmony_ci			pfd_end = pfd + walk->len;
91362306a36Sopenharmony_ci			for (; pfd != pfd_end; pfd++) {
91462306a36Sopenharmony_ci				/*
91562306a36Sopenharmony_ci				 * Fish for events. If we found one, record it
91662306a36Sopenharmony_ci				 * and kill poll_table->_qproc, so we don't
91762306a36Sopenharmony_ci				 * needlessly register any other waiters after
91862306a36Sopenharmony_ci				 * this. They'll get immediately deregistered
91962306a36Sopenharmony_ci				 * when we break out and return.
92062306a36Sopenharmony_ci				 */
92162306a36Sopenharmony_ci				if (do_pollfd(pfd, pt, &can_busy_loop,
92262306a36Sopenharmony_ci					      busy_flag)) {
92362306a36Sopenharmony_ci					count++;
92462306a36Sopenharmony_ci					pt->_qproc = NULL;
92562306a36Sopenharmony_ci					/* found something, stop busy polling */
92662306a36Sopenharmony_ci					busy_flag = 0;
92762306a36Sopenharmony_ci					can_busy_loop = false;
92862306a36Sopenharmony_ci				}
92962306a36Sopenharmony_ci			}
93062306a36Sopenharmony_ci		}
93162306a36Sopenharmony_ci		/*
93262306a36Sopenharmony_ci		 * All waiters have already been registered, so don't provide
93362306a36Sopenharmony_ci		 * a poll_table->_qproc to them on the next loop iteration.
93462306a36Sopenharmony_ci		 */
93562306a36Sopenharmony_ci		pt->_qproc = NULL;
93662306a36Sopenharmony_ci		if (!count) {
93762306a36Sopenharmony_ci			count = wait->error;
93862306a36Sopenharmony_ci			if (signal_pending(current))
93962306a36Sopenharmony_ci				count = -ERESTARTNOHAND;
94062306a36Sopenharmony_ci		}
94162306a36Sopenharmony_ci		if (count || timed_out)
94262306a36Sopenharmony_ci			break;
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci		/* only if found POLL_BUSY_LOOP sockets && not out of time */
94562306a36Sopenharmony_ci		if (can_busy_loop && !need_resched()) {
94662306a36Sopenharmony_ci			if (!busy_start) {
94762306a36Sopenharmony_ci				busy_start = busy_loop_current_time();
94862306a36Sopenharmony_ci				continue;
94962306a36Sopenharmony_ci			}
95062306a36Sopenharmony_ci			if (!busy_loop_timeout(busy_start))
95162306a36Sopenharmony_ci				continue;
95262306a36Sopenharmony_ci		}
95362306a36Sopenharmony_ci		busy_flag = 0;
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_ci		/*
95662306a36Sopenharmony_ci		 * If this is the first loop and we have a timeout
95762306a36Sopenharmony_ci		 * given, then we convert to ktime_t and set the to
95862306a36Sopenharmony_ci		 * pointer to the expiry value.
95962306a36Sopenharmony_ci		 */
96062306a36Sopenharmony_ci		if (end_time && !to) {
96162306a36Sopenharmony_ci			expire = timespec64_to_ktime(*end_time);
96262306a36Sopenharmony_ci			to = &expire;
96362306a36Sopenharmony_ci		}
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci		if (!poll_schedule_timeout(wait, TASK_INTERRUPTIBLE, to, slack))
96662306a36Sopenharmony_ci			timed_out = 1;
96762306a36Sopenharmony_ci	}
96862306a36Sopenharmony_ci	return count;
96962306a36Sopenharmony_ci}
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_ci#define N_STACK_PPS ((sizeof(stack_pps) - sizeof(struct poll_list))  / \
97262306a36Sopenharmony_ci			sizeof(struct pollfd))
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_cistatic int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds,
97562306a36Sopenharmony_ci		struct timespec64 *end_time)
97662306a36Sopenharmony_ci{
97762306a36Sopenharmony_ci	struct poll_wqueues table;
97862306a36Sopenharmony_ci	int err = -EFAULT, fdcount, len;
97962306a36Sopenharmony_ci	/* Allocate small arguments on the stack to save memory and be
98062306a36Sopenharmony_ci	   faster - use long to make sure the buffer is aligned properly
98162306a36Sopenharmony_ci	   on 64 bit archs to avoid unaligned access */
98262306a36Sopenharmony_ci	long stack_pps[POLL_STACK_ALLOC/sizeof(long)];
98362306a36Sopenharmony_ci	struct poll_list *const head = (struct poll_list *)stack_pps;
98462306a36Sopenharmony_ci 	struct poll_list *walk = head;
98562306a36Sopenharmony_ci 	unsigned long todo = nfds;
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci	if (nfds > rlimit(RLIMIT_NOFILE))
98862306a36Sopenharmony_ci		return -EINVAL;
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci	len = min_t(unsigned int, nfds, N_STACK_PPS);
99162306a36Sopenharmony_ci	for (;;) {
99262306a36Sopenharmony_ci		walk->next = NULL;
99362306a36Sopenharmony_ci		walk->len = len;
99462306a36Sopenharmony_ci		if (!len)
99562306a36Sopenharmony_ci			break;
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci		if (copy_from_user(walk->entries, ufds + nfds-todo,
99862306a36Sopenharmony_ci					sizeof(struct pollfd) * walk->len))
99962306a36Sopenharmony_ci			goto out_fds;
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_ci		todo -= walk->len;
100262306a36Sopenharmony_ci		if (!todo)
100362306a36Sopenharmony_ci			break;
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_ci		len = min(todo, POLLFD_PER_PAGE);
100662306a36Sopenharmony_ci		walk = walk->next = kmalloc(struct_size(walk, entries, len),
100762306a36Sopenharmony_ci					    GFP_KERNEL);
100862306a36Sopenharmony_ci		if (!walk) {
100962306a36Sopenharmony_ci			err = -ENOMEM;
101062306a36Sopenharmony_ci			goto out_fds;
101162306a36Sopenharmony_ci		}
101262306a36Sopenharmony_ci	}
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci	poll_initwait(&table);
101562306a36Sopenharmony_ci	fdcount = do_poll(head, &table, end_time);
101662306a36Sopenharmony_ci	poll_freewait(&table);
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	if (!user_write_access_begin(ufds, nfds * sizeof(*ufds)))
101962306a36Sopenharmony_ci		goto out_fds;
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_ci	for (walk = head; walk; walk = walk->next) {
102262306a36Sopenharmony_ci		struct pollfd *fds = walk->entries;
102362306a36Sopenharmony_ci		int j;
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci		for (j = walk->len; j; fds++, ufds++, j--)
102662306a36Sopenharmony_ci			unsafe_put_user(fds->revents, &ufds->revents, Efault);
102762306a36Sopenharmony_ci  	}
102862306a36Sopenharmony_ci	user_write_access_end();
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_ci	err = fdcount;
103162306a36Sopenharmony_ciout_fds:
103262306a36Sopenharmony_ci	walk = head->next;
103362306a36Sopenharmony_ci	while (walk) {
103462306a36Sopenharmony_ci		struct poll_list *pos = walk;
103562306a36Sopenharmony_ci		walk = walk->next;
103662306a36Sopenharmony_ci		kfree(pos);
103762306a36Sopenharmony_ci	}
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	return err;
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ciEfault:
104262306a36Sopenharmony_ci	user_write_access_end();
104362306a36Sopenharmony_ci	err = -EFAULT;
104462306a36Sopenharmony_ci	goto out_fds;
104562306a36Sopenharmony_ci}
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_cistatic long do_restart_poll(struct restart_block *restart_block)
104862306a36Sopenharmony_ci{
104962306a36Sopenharmony_ci	struct pollfd __user *ufds = restart_block->poll.ufds;
105062306a36Sopenharmony_ci	int nfds = restart_block->poll.nfds;
105162306a36Sopenharmony_ci	struct timespec64 *to = NULL, end_time;
105262306a36Sopenharmony_ci	int ret;
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	if (restart_block->poll.has_timeout) {
105562306a36Sopenharmony_ci		end_time.tv_sec = restart_block->poll.tv_sec;
105662306a36Sopenharmony_ci		end_time.tv_nsec = restart_block->poll.tv_nsec;
105762306a36Sopenharmony_ci		to = &end_time;
105862306a36Sopenharmony_ci	}
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	ret = do_sys_poll(ufds, nfds, to);
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci	if (ret == -ERESTARTNOHAND)
106362306a36Sopenharmony_ci		ret = set_restart_fn(restart_block, do_restart_poll);
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	return ret;
106662306a36Sopenharmony_ci}
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ciSYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds,
106962306a36Sopenharmony_ci		int, timeout_msecs)
107062306a36Sopenharmony_ci{
107162306a36Sopenharmony_ci	struct timespec64 end_time, *to = NULL;
107262306a36Sopenharmony_ci	int ret;
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci	if (timeout_msecs >= 0) {
107562306a36Sopenharmony_ci		to = &end_time;
107662306a36Sopenharmony_ci		poll_select_set_timeout(to, timeout_msecs / MSEC_PER_SEC,
107762306a36Sopenharmony_ci			NSEC_PER_MSEC * (timeout_msecs % MSEC_PER_SEC));
107862306a36Sopenharmony_ci	}
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	ret = do_sys_poll(ufds, nfds, to);
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci	if (ret == -ERESTARTNOHAND) {
108362306a36Sopenharmony_ci		struct restart_block *restart_block;
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci		restart_block = &current->restart_block;
108662306a36Sopenharmony_ci		restart_block->poll.ufds = ufds;
108762306a36Sopenharmony_ci		restart_block->poll.nfds = nfds;
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci		if (timeout_msecs >= 0) {
109062306a36Sopenharmony_ci			restart_block->poll.tv_sec = end_time.tv_sec;
109162306a36Sopenharmony_ci			restart_block->poll.tv_nsec = end_time.tv_nsec;
109262306a36Sopenharmony_ci			restart_block->poll.has_timeout = 1;
109362306a36Sopenharmony_ci		} else
109462306a36Sopenharmony_ci			restart_block->poll.has_timeout = 0;
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci		ret = set_restart_fn(restart_block, do_restart_poll);
109762306a36Sopenharmony_ci	}
109862306a36Sopenharmony_ci	return ret;
109962306a36Sopenharmony_ci}
110062306a36Sopenharmony_ci
110162306a36Sopenharmony_ciSYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
110262306a36Sopenharmony_ci		struct __kernel_timespec __user *, tsp, const sigset_t __user *, sigmask,
110362306a36Sopenharmony_ci		size_t, sigsetsize)
110462306a36Sopenharmony_ci{
110562306a36Sopenharmony_ci	struct timespec64 ts, end_time, *to = NULL;
110662306a36Sopenharmony_ci	int ret;
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_ci	if (tsp) {
110962306a36Sopenharmony_ci		if (get_timespec64(&ts, tsp))
111062306a36Sopenharmony_ci			return -EFAULT;
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci		to = &end_time;
111362306a36Sopenharmony_ci		if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
111462306a36Sopenharmony_ci			return -EINVAL;
111562306a36Sopenharmony_ci	}
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_ci	ret = set_user_sigmask(sigmask, sigsetsize);
111862306a36Sopenharmony_ci	if (ret)
111962306a36Sopenharmony_ci		return ret;
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	ret = do_sys_poll(ufds, nfds, to);
112262306a36Sopenharmony_ci	return poll_select_finish(&end_time, tsp, PT_TIMESPEC, ret);
112362306a36Sopenharmony_ci}
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci#if defined(CONFIG_COMPAT_32BIT_TIME) && !defined(CONFIG_64BIT)
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_ciSYSCALL_DEFINE5(ppoll_time32, struct pollfd __user *, ufds, unsigned int, nfds,
112862306a36Sopenharmony_ci		struct old_timespec32 __user *, tsp, const sigset_t __user *, sigmask,
112962306a36Sopenharmony_ci		size_t, sigsetsize)
113062306a36Sopenharmony_ci{
113162306a36Sopenharmony_ci	struct timespec64 ts, end_time, *to = NULL;
113262306a36Sopenharmony_ci	int ret;
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	if (tsp) {
113562306a36Sopenharmony_ci		if (get_old_timespec32(&ts, tsp))
113662306a36Sopenharmony_ci			return -EFAULT;
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci		to = &end_time;
113962306a36Sopenharmony_ci		if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
114062306a36Sopenharmony_ci			return -EINVAL;
114162306a36Sopenharmony_ci	}
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci	ret = set_user_sigmask(sigmask, sigsetsize);
114462306a36Sopenharmony_ci	if (ret)
114562306a36Sopenharmony_ci		return ret;
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_ci	ret = do_sys_poll(ufds, nfds, to);
114862306a36Sopenharmony_ci	return poll_select_finish(&end_time, tsp, PT_OLD_TIMESPEC, ret);
114962306a36Sopenharmony_ci}
115062306a36Sopenharmony_ci#endif
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_ci#ifdef CONFIG_COMPAT
115362306a36Sopenharmony_ci#define __COMPAT_NFDBITS       (8 * sizeof(compat_ulong_t))
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci/*
115662306a36Sopenharmony_ci * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
115762306a36Sopenharmony_ci * 64-bit unsigned longs.
115862306a36Sopenharmony_ci */
115962306a36Sopenharmony_cistatic
116062306a36Sopenharmony_ciint compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
116162306a36Sopenharmony_ci			unsigned long *fdset)
116262306a36Sopenharmony_ci{
116362306a36Sopenharmony_ci	if (ufdset) {
116462306a36Sopenharmony_ci		return compat_get_bitmap(fdset, ufdset, nr);
116562306a36Sopenharmony_ci	} else {
116662306a36Sopenharmony_ci		zero_fd_set(nr, fdset);
116762306a36Sopenharmony_ci		return 0;
116862306a36Sopenharmony_ci	}
116962306a36Sopenharmony_ci}
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_cistatic
117262306a36Sopenharmony_ciint compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
117362306a36Sopenharmony_ci		      unsigned long *fdset)
117462306a36Sopenharmony_ci{
117562306a36Sopenharmony_ci	if (!ufdset)
117662306a36Sopenharmony_ci		return 0;
117762306a36Sopenharmony_ci	return compat_put_bitmap(ufdset, fdset, nr);
117862306a36Sopenharmony_ci}
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_ci/*
118262306a36Sopenharmony_ci * This is a virtual copy of sys_select from fs/select.c and probably
118362306a36Sopenharmony_ci * should be compared to it from time to time
118462306a36Sopenharmony_ci */
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci/*
118762306a36Sopenharmony_ci * We can actually return ERESTARTSYS instead of EINTR, but I'd
118862306a36Sopenharmony_ci * like to be certain this leads to no problems. So I return
118962306a36Sopenharmony_ci * EINTR just for safety.
119062306a36Sopenharmony_ci *
119162306a36Sopenharmony_ci * Update: ERESTARTSYS breaks at least the xview clock binary, so
119262306a36Sopenharmony_ci * I'm trying ERESTARTNOHAND which restart only when you want to.
119362306a36Sopenharmony_ci */
119462306a36Sopenharmony_cistatic int compat_core_sys_select(int n, compat_ulong_t __user *inp,
119562306a36Sopenharmony_ci	compat_ulong_t __user *outp, compat_ulong_t __user *exp,
119662306a36Sopenharmony_ci	struct timespec64 *end_time)
119762306a36Sopenharmony_ci{
119862306a36Sopenharmony_ci	fd_set_bits fds;
119962306a36Sopenharmony_ci	void *bits;
120062306a36Sopenharmony_ci	int size, max_fds, ret = -EINVAL;
120162306a36Sopenharmony_ci	struct fdtable *fdt;
120262306a36Sopenharmony_ci	long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci	if (n < 0)
120562306a36Sopenharmony_ci		goto out_nofds;
120662306a36Sopenharmony_ci
120762306a36Sopenharmony_ci	/* max_fds can increase, so grab it once to avoid race */
120862306a36Sopenharmony_ci	rcu_read_lock();
120962306a36Sopenharmony_ci	fdt = files_fdtable(current->files);
121062306a36Sopenharmony_ci	max_fds = fdt->max_fds;
121162306a36Sopenharmony_ci	rcu_read_unlock();
121262306a36Sopenharmony_ci	if (n > max_fds)
121362306a36Sopenharmony_ci		n = max_fds;
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci	/*
121662306a36Sopenharmony_ci	 * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
121762306a36Sopenharmony_ci	 * since we used fdset we need to allocate memory in units of
121862306a36Sopenharmony_ci	 * long-words.
121962306a36Sopenharmony_ci	 */
122062306a36Sopenharmony_ci	size = FDS_BYTES(n);
122162306a36Sopenharmony_ci	bits = stack_fds;
122262306a36Sopenharmony_ci	if (size > sizeof(stack_fds) / 6) {
122362306a36Sopenharmony_ci		bits = kmalloc_array(6, size, GFP_KERNEL);
122462306a36Sopenharmony_ci		ret = -ENOMEM;
122562306a36Sopenharmony_ci		if (!bits)
122662306a36Sopenharmony_ci			goto out_nofds;
122762306a36Sopenharmony_ci	}
122862306a36Sopenharmony_ci	fds.in      = (unsigned long *)  bits;
122962306a36Sopenharmony_ci	fds.out     = (unsigned long *) (bits +   size);
123062306a36Sopenharmony_ci	fds.ex      = (unsigned long *) (bits + 2*size);
123162306a36Sopenharmony_ci	fds.res_in  = (unsigned long *) (bits + 3*size);
123262306a36Sopenharmony_ci	fds.res_out = (unsigned long *) (bits + 4*size);
123362306a36Sopenharmony_ci	fds.res_ex  = (unsigned long *) (bits + 5*size);
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci	if ((ret = compat_get_fd_set(n, inp, fds.in)) ||
123662306a36Sopenharmony_ci	    (ret = compat_get_fd_set(n, outp, fds.out)) ||
123762306a36Sopenharmony_ci	    (ret = compat_get_fd_set(n, exp, fds.ex)))
123862306a36Sopenharmony_ci		goto out;
123962306a36Sopenharmony_ci	zero_fd_set(n, fds.res_in);
124062306a36Sopenharmony_ci	zero_fd_set(n, fds.res_out);
124162306a36Sopenharmony_ci	zero_fd_set(n, fds.res_ex);
124262306a36Sopenharmony_ci
124362306a36Sopenharmony_ci	ret = do_select(n, &fds, end_time);
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_ci	if (ret < 0)
124662306a36Sopenharmony_ci		goto out;
124762306a36Sopenharmony_ci	if (!ret) {
124862306a36Sopenharmony_ci		ret = -ERESTARTNOHAND;
124962306a36Sopenharmony_ci		if (signal_pending(current))
125062306a36Sopenharmony_ci			goto out;
125162306a36Sopenharmony_ci		ret = 0;
125262306a36Sopenharmony_ci	}
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci	if (compat_set_fd_set(n, inp, fds.res_in) ||
125562306a36Sopenharmony_ci	    compat_set_fd_set(n, outp, fds.res_out) ||
125662306a36Sopenharmony_ci	    compat_set_fd_set(n, exp, fds.res_ex))
125762306a36Sopenharmony_ci		ret = -EFAULT;
125862306a36Sopenharmony_ciout:
125962306a36Sopenharmony_ci	if (bits != stack_fds)
126062306a36Sopenharmony_ci		kfree(bits);
126162306a36Sopenharmony_ciout_nofds:
126262306a36Sopenharmony_ci	return ret;
126362306a36Sopenharmony_ci}
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_cistatic int do_compat_select(int n, compat_ulong_t __user *inp,
126662306a36Sopenharmony_ci	compat_ulong_t __user *outp, compat_ulong_t __user *exp,
126762306a36Sopenharmony_ci	struct old_timeval32 __user *tvp)
126862306a36Sopenharmony_ci{
126962306a36Sopenharmony_ci	struct timespec64 end_time, *to = NULL;
127062306a36Sopenharmony_ci	struct old_timeval32 tv;
127162306a36Sopenharmony_ci	int ret;
127262306a36Sopenharmony_ci
127362306a36Sopenharmony_ci	if (tvp) {
127462306a36Sopenharmony_ci		if (copy_from_user(&tv, tvp, sizeof(tv)))
127562306a36Sopenharmony_ci			return -EFAULT;
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ci		to = &end_time;
127862306a36Sopenharmony_ci		if (poll_select_set_timeout(to,
127962306a36Sopenharmony_ci				tv.tv_sec + (tv.tv_usec / USEC_PER_SEC),
128062306a36Sopenharmony_ci				(tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC))
128162306a36Sopenharmony_ci			return -EINVAL;
128262306a36Sopenharmony_ci	}
128362306a36Sopenharmony_ci
128462306a36Sopenharmony_ci	ret = compat_core_sys_select(n, inp, outp, exp, to);
128562306a36Sopenharmony_ci	return poll_select_finish(&end_time, tvp, PT_OLD_TIMEVAL, ret);
128662306a36Sopenharmony_ci}
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ciCOMPAT_SYSCALL_DEFINE5(select, int, n, compat_ulong_t __user *, inp,
128962306a36Sopenharmony_ci	compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
129062306a36Sopenharmony_ci	struct old_timeval32 __user *, tvp)
129162306a36Sopenharmony_ci{
129262306a36Sopenharmony_ci	return do_compat_select(n, inp, outp, exp, tvp);
129362306a36Sopenharmony_ci}
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_cistruct compat_sel_arg_struct {
129662306a36Sopenharmony_ci	compat_ulong_t n;
129762306a36Sopenharmony_ci	compat_uptr_t inp;
129862306a36Sopenharmony_ci	compat_uptr_t outp;
129962306a36Sopenharmony_ci	compat_uptr_t exp;
130062306a36Sopenharmony_ci	compat_uptr_t tvp;
130162306a36Sopenharmony_ci};
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ciCOMPAT_SYSCALL_DEFINE1(old_select, struct compat_sel_arg_struct __user *, arg)
130462306a36Sopenharmony_ci{
130562306a36Sopenharmony_ci	struct compat_sel_arg_struct a;
130662306a36Sopenharmony_ci
130762306a36Sopenharmony_ci	if (copy_from_user(&a, arg, sizeof(a)))
130862306a36Sopenharmony_ci		return -EFAULT;
130962306a36Sopenharmony_ci	return do_compat_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp),
131062306a36Sopenharmony_ci				compat_ptr(a.exp), compat_ptr(a.tvp));
131162306a36Sopenharmony_ci}
131262306a36Sopenharmony_ci
131362306a36Sopenharmony_cistatic long do_compat_pselect(int n, compat_ulong_t __user *inp,
131462306a36Sopenharmony_ci	compat_ulong_t __user *outp, compat_ulong_t __user *exp,
131562306a36Sopenharmony_ci	void __user *tsp, compat_sigset_t __user *sigmask,
131662306a36Sopenharmony_ci	compat_size_t sigsetsize, enum poll_time_type type)
131762306a36Sopenharmony_ci{
131862306a36Sopenharmony_ci	struct timespec64 ts, end_time, *to = NULL;
131962306a36Sopenharmony_ci	int ret;
132062306a36Sopenharmony_ci
132162306a36Sopenharmony_ci	if (tsp) {
132262306a36Sopenharmony_ci		switch (type) {
132362306a36Sopenharmony_ci		case PT_OLD_TIMESPEC:
132462306a36Sopenharmony_ci			if (get_old_timespec32(&ts, tsp))
132562306a36Sopenharmony_ci				return -EFAULT;
132662306a36Sopenharmony_ci			break;
132762306a36Sopenharmony_ci		case PT_TIMESPEC:
132862306a36Sopenharmony_ci			if (get_timespec64(&ts, tsp))
132962306a36Sopenharmony_ci				return -EFAULT;
133062306a36Sopenharmony_ci			break;
133162306a36Sopenharmony_ci		default:
133262306a36Sopenharmony_ci			BUG();
133362306a36Sopenharmony_ci		}
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_ci		to = &end_time;
133662306a36Sopenharmony_ci		if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
133762306a36Sopenharmony_ci			return -EINVAL;
133862306a36Sopenharmony_ci	}
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci	ret = set_compat_user_sigmask(sigmask, sigsetsize);
134162306a36Sopenharmony_ci	if (ret)
134262306a36Sopenharmony_ci		return ret;
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_ci	ret = compat_core_sys_select(n, inp, outp, exp, to);
134562306a36Sopenharmony_ci	return poll_select_finish(&end_time, tsp, type, ret);
134662306a36Sopenharmony_ci}
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_cistruct compat_sigset_argpack {
134962306a36Sopenharmony_ci	compat_uptr_t p;
135062306a36Sopenharmony_ci	compat_size_t size;
135162306a36Sopenharmony_ci};
135262306a36Sopenharmony_cistatic inline int get_compat_sigset_argpack(struct compat_sigset_argpack *to,
135362306a36Sopenharmony_ci					    struct compat_sigset_argpack __user *from)
135462306a36Sopenharmony_ci{
135562306a36Sopenharmony_ci	if (from) {
135662306a36Sopenharmony_ci		if (!user_read_access_begin(from, sizeof(*from)))
135762306a36Sopenharmony_ci			return -EFAULT;
135862306a36Sopenharmony_ci		unsafe_get_user(to->p, &from->p, Efault);
135962306a36Sopenharmony_ci		unsafe_get_user(to->size, &from->size, Efault);
136062306a36Sopenharmony_ci		user_read_access_end();
136162306a36Sopenharmony_ci	}
136262306a36Sopenharmony_ci	return 0;
136362306a36Sopenharmony_ciEfault:
136462306a36Sopenharmony_ci	user_access_end();
136562306a36Sopenharmony_ci	return -EFAULT;
136662306a36Sopenharmony_ci}
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_ciCOMPAT_SYSCALL_DEFINE6(pselect6_time64, int, n, compat_ulong_t __user *, inp,
136962306a36Sopenharmony_ci	compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
137062306a36Sopenharmony_ci	struct __kernel_timespec __user *, tsp, void __user *, sig)
137162306a36Sopenharmony_ci{
137262306a36Sopenharmony_ci	struct compat_sigset_argpack x = {0, 0};
137362306a36Sopenharmony_ci
137462306a36Sopenharmony_ci	if (get_compat_sigset_argpack(&x, sig))
137562306a36Sopenharmony_ci		return -EFAULT;
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ci	return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(x.p),
137862306a36Sopenharmony_ci				 x.size, PT_TIMESPEC);
137962306a36Sopenharmony_ci}
138062306a36Sopenharmony_ci
138162306a36Sopenharmony_ci#if defined(CONFIG_COMPAT_32BIT_TIME)
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ciCOMPAT_SYSCALL_DEFINE6(pselect6_time32, int, n, compat_ulong_t __user *, inp,
138462306a36Sopenharmony_ci	compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
138562306a36Sopenharmony_ci	struct old_timespec32 __user *, tsp, void __user *, sig)
138662306a36Sopenharmony_ci{
138762306a36Sopenharmony_ci	struct compat_sigset_argpack x = {0, 0};
138862306a36Sopenharmony_ci
138962306a36Sopenharmony_ci	if (get_compat_sigset_argpack(&x, sig))
139062306a36Sopenharmony_ci		return -EFAULT;
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_ci	return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(x.p),
139362306a36Sopenharmony_ci				 x.size, PT_OLD_TIMESPEC);
139462306a36Sopenharmony_ci}
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci#endif
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci#if defined(CONFIG_COMPAT_32BIT_TIME)
139962306a36Sopenharmony_ciCOMPAT_SYSCALL_DEFINE5(ppoll_time32, struct pollfd __user *, ufds,
140062306a36Sopenharmony_ci	unsigned int,  nfds, struct old_timespec32 __user *, tsp,
140162306a36Sopenharmony_ci	const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize)
140262306a36Sopenharmony_ci{
140362306a36Sopenharmony_ci	struct timespec64 ts, end_time, *to = NULL;
140462306a36Sopenharmony_ci	int ret;
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_ci	if (tsp) {
140762306a36Sopenharmony_ci		if (get_old_timespec32(&ts, tsp))
140862306a36Sopenharmony_ci			return -EFAULT;
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_ci		to = &end_time;
141162306a36Sopenharmony_ci		if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
141262306a36Sopenharmony_ci			return -EINVAL;
141362306a36Sopenharmony_ci	}
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_ci	ret = set_compat_user_sigmask(sigmask, sigsetsize);
141662306a36Sopenharmony_ci	if (ret)
141762306a36Sopenharmony_ci		return ret;
141862306a36Sopenharmony_ci
141962306a36Sopenharmony_ci	ret = do_sys_poll(ufds, nfds, to);
142062306a36Sopenharmony_ci	return poll_select_finish(&end_time, tsp, PT_OLD_TIMESPEC, ret);
142162306a36Sopenharmony_ci}
142262306a36Sopenharmony_ci#endif
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_ci/* New compat syscall for 64 bit time_t*/
142562306a36Sopenharmony_ciCOMPAT_SYSCALL_DEFINE5(ppoll_time64, struct pollfd __user *, ufds,
142662306a36Sopenharmony_ci	unsigned int,  nfds, struct __kernel_timespec __user *, tsp,
142762306a36Sopenharmony_ci	const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize)
142862306a36Sopenharmony_ci{
142962306a36Sopenharmony_ci	struct timespec64 ts, end_time, *to = NULL;
143062306a36Sopenharmony_ci	int ret;
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_ci	if (tsp) {
143362306a36Sopenharmony_ci		if (get_timespec64(&ts, tsp))
143462306a36Sopenharmony_ci			return -EFAULT;
143562306a36Sopenharmony_ci
143662306a36Sopenharmony_ci		to = &end_time;
143762306a36Sopenharmony_ci		if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
143862306a36Sopenharmony_ci			return -EINVAL;
143962306a36Sopenharmony_ci	}
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci	ret = set_compat_user_sigmask(sigmask, sigsetsize);
144262306a36Sopenharmony_ci	if (ret)
144362306a36Sopenharmony_ci		return ret;
144462306a36Sopenharmony_ci
144562306a36Sopenharmony_ci	ret = do_sys_poll(ufds, nfds, to);
144662306a36Sopenharmony_ci	return poll_select_finish(&end_time, tsp, PT_TIMESPEC, ret);
144762306a36Sopenharmony_ci}
144862306a36Sopenharmony_ci
144962306a36Sopenharmony_ci#endif
1450