diff options
Diffstat (limited to 'ipc')
| -rw-r--r-- | ipc/mqueue.c | 14 | ||||
| -rw-r--r-- | ipc/sem.c | 25 | 
2 files changed, 25 insertions, 14 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 7c08eb3c258d..54cb6264f8cf 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -45,6 +45,7 @@  struct mqueue_fs_context {  	struct ipc_namespace	*ipc_ns; +	bool			 newns;	/* Set if newly created ipc namespace */  };  #define MQUEUE_MAGIC	0x19800202 @@ -427,6 +428,14 @@ static int mqueue_get_tree(struct fs_context *fc)  {  	struct mqueue_fs_context *ctx = fc->fs_private; +	/* +	 * With a newly created ipc namespace, we don't need to do a search +	 * for an ipc namespace match, but we still need to set s_fs_info. +	 */ +	if (ctx->newns) { +		fc->s_fs_info = ctx->ipc_ns; +		return get_tree_nodev(fc, mqueue_fill_super); +	}  	return get_tree_keyed(fc, mqueue_fill_super, ctx->ipc_ns);  } @@ -454,6 +463,10 @@ static int mqueue_init_fs_context(struct fs_context *fc)  	return 0;  } +/* + * mq_init_ns() is currently the only caller of mq_create_mount(). + * So the ns parameter is always a newly created ipc namespace. + */  static struct vfsmount *mq_create_mount(struct ipc_namespace *ns)  {  	struct mqueue_fs_context *ctx; @@ -465,6 +478,7 @@ static struct vfsmount *mq_create_mount(struct ipc_namespace *ns)  		return ERR_CAST(fc);  	ctx = fc->fs_private; +	ctx->newns = true;  	put_ipc_ns(ctx->ipc_ns);  	ctx->ipc_ns = get_ipc_ns(ns);  	put_user_ns(fc->user_ns); diff --git a/ipc/sem.c b/ipc/sem.c index 0dbdb98fdf2d..c8496f98b139 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -766,7 +766,6 @@ static int perform_atomic_semop(struct sem_array *sma, struct sem_queue *q)  	for (sop = sops; sop < sops + nsops; sop++) {  		curr = &sma->sems[sop->sem_num];  		sem_op = sop->sem_op; -		result = curr->semval;  		if (sop->sem_flg & SEM_UNDO) {  			int undo = un->semadj[sop->sem_num] - sem_op; @@ -1430,7 +1429,6 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,  	if (err)  		goto out_rcu_wakeup; -	err = -EACCES;  	switch (cmd) {  	case GETALL:  	{ @@ -1995,7 +1993,9 @@ long __do_semtimedop(int semid, struct sembuf *sops,  	int max, locknum;  	bool undos = false, alter = false, dupsop = false;  	struct sem_queue queue; -	unsigned long dup = 0, jiffies_left = 0; +	unsigned long dup = 0; +	ktime_t expires, *exp = NULL; +	bool timed_out = false;  	if (nsops < 1 || semid < 0)  		return -EINVAL; @@ -2003,12 +2003,11 @@ long __do_semtimedop(int semid, struct sembuf *sops,  		return -E2BIG;  	if (timeout) { -		if (timeout->tv_sec < 0 || timeout->tv_nsec < 0 || -			timeout->tv_nsec >= 1000000000L) { -			error = -EINVAL; -			goto out; -		} -		jiffies_left = timespec64_to_jiffies(timeout); +		if (!timespec64_valid(timeout)) +			return -EINVAL; +		expires = ktime_add_safe(ktime_get(), +				timespec64_to_ktime(*timeout)); +		exp = &expires;  	} @@ -2166,10 +2165,8 @@ long __do_semtimedop(int semid, struct sembuf *sops,  		sem_unlock(sma, locknum);  		rcu_read_unlock(); -		if (timeout) -			jiffies_left = schedule_timeout(jiffies_left); -		else -			schedule(); +		timed_out = !schedule_hrtimeout_range(exp, +				current->timer_slack_ns, HRTIMER_MODE_ABS);  		/*  		 * fastpath: the semop has completed, either successfully or @@ -2210,7 +2207,7 @@ long __do_semtimedop(int semid, struct sembuf *sops,  		/*  		 * If an interrupt occurred we have to clean up the queue.  		 */ -		if (timeout && jiffies_left == 0) +		if (timed_out)  			error = -EAGAIN;  	} while (error == -EINTR && !signal_pending(current)); /* spurious */  | 
