nbd: fix/cleanup the usage of kernel_dequeue_signal()
Subsystems (2)
cover nbd: fix/cleanup the usage of kernel_dequeue_signal()
On top of
signal-turn-dequeue_signal_lock-into-kernel_dequeue_signal
in -mm plus
signal-turn-dequeue_signal_lock-into-kernel_dequeue_signal-fix
I sent today.
Another untested (but simple) series. Needs an ack from Markus or should be ignored, I can easily miss something.
Oleg.
PATCH 1/3 nbd: nbd_thread_send: remove the unnecessary kernel_dequeue_signal()
nbd_thread_send() does kernel_dequeue_signal() at the end for no reason, it is fine to exit with the pending SIGKILL.
Not sure it really needs another kernel_dequeue_signal() inside the main loop, we know that signal_pending() means SIGKILL. But probably we want to clear TIF_SIGPENDING before sock_shutdown().
--- drivers/block/nbd.c | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-)
drivers/block/nbd.c +0 -4
@@ -586,10 +586,6 @@ static int nbd_thread_send(void *data) nbd->task_send =NULL ;spin_unlock_irqrestore (&nbd->tasks_lock, flags); -/* Clear maybe pending signals */ -if (signal_pending (current)) -kernel_dequeue_signal (NULL ); -return 0 ; }
Signature · 1 line
1.5.5.1
Re: [PATCH -mm 1/3] nbd: nbd_thread_send: remove the unnecessary kernel_dequeue_signal()
Quoted 6 lines · Oleg Nesterov
nbd_thread_send()doeskernel_dequeue_signal()at the end for no reason, it is fine to exit with the pending SIGKILL.Not sure it really needs another
kernel_dequeue_signal()inside the main loop, we know thatsignal_pending()means SIGKILL. But probably we want to clearTIF_SIGPENDINGbeforesock_shutdown().
Yes, I don't think it would be good to go into a tcp socket shutdown with a pending signal although I don't know if this would make difficulties.
I will apply the patch to my tree and send it out as pull request to Jens as usual.
Thanks,
Markus
Quoted 25 lines
Signed-off-by Oleg Nesterov <[email protected]>--- drivers/block/nbd.c | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-)drivers/block/nbd.c +0
-4@@ -586,10 +586,6 @@ static int nbd_thread_send(void *data) nbd->task_send =NULL ;spin_unlock_irqrestore (&nbd->tasks_lock, flags); -/* Clear maybe pending signals */ -if (signal_pending (current)) -kernel_dequeue_signal (NULL ); -return 0 ; }Signature · 1 line
1.5.5.1
Signature · 4 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
PATCH 2/3 nbd: nbd_thread_recv: remove the buggy kernel_dequeue_signal()
In reply to Oleg Nesterovnbd_thread_recv() is called by userspace, it is very wrong to dequeue and throw out a signal.
I do not understand why nbd_thread_recv() (and nbd_thread_send() btw) does sock_shutdown(); the caller, __nbd_ioctl(NBD_DO_IT) does this too.
--- drivers/block/nbd.c | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-)
drivers/block/nbd.c +2 -3
@@ -444,9 +444,8 @@ static int nbd_thread_recv(struct nbd_device *nbd)spin_unlock_irqrestore (&nbd->tasks_lock, flags);if (signal_pending (current)) { - ret =kernel_dequeue_signal (NULL ); -dev_warn (nbd_to_dev (nbd),"pid %d, %s, got signal %d\n" , -task_pid_nr (current), current->comm, ret); +dev_warn (nbd_to_dev (nbd),"pid %d, %s, got signal" , +task_pid_nr (current), current->comm);mutex_lock (&nbd->tx_lock);sock_shutdown (nbd);mutex_unlock (&nbd->tx_lock);
Signature · 1 line
1.5.5.1
Re: [PATCH -mm 2/3] nbd: nbd_thread_recv: remove the buggy kernel_dequeue_signal()
Hi Oleg,
Quoted 2 lines · Oleg Nesterov
nbd_thread_recv()is called by userspace, it is very wrong to dequeue and throw out a signal.
This signal handling for a userspace process is implicitly implemented for several years already through the timeout handling. This is nothing new and could potentially break userspace if someone disconnects NBD using the kill command. As we expose the appropriate PID of the process as well this is possible to be used in an init script.
So I am not sure about this patch yet.
Quoted 3 lines
I do not understand why
nbd_thread_recv()(andnbd_thread_send()btw) doessock_shutdown(); the caller,__nbd_ioctl(NBD_DO_IT)does this too.
Yes indeed. This has to be fixed as well, thanks.
Best Regards,
Markus
Quoted 26 lines
Signed-off-by Oleg Nesterov <[email protected]>--- drivers/block/nbd.c | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-)drivers/block/nbd.c +2
-3@@ -444,9 +444,8 @@ static int nbd_thread_recv(struct nbd_device *nbd)spin_unlock_irqrestore (&nbd->tasks_lock, flags);if (signal_pending (current)) { - ret =kernel_dequeue_signal (NULL ); -dev_warn (nbd_to_dev (nbd),"pid %d, %s, got signal %d\n" , -task_pid_nr (current), current->comm, ret); +dev_warn (nbd_to_dev (nbd),"pid %d, %s, got signal" , +task_pid_nr (current), current->comm);mutex_lock (&nbd->tx_lock);sock_shutdown (nbd);mutex_unlock (&nbd->tx_lock);Signature · 1 line
1.5.5.1
Signature · 4 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
Re: [PATCH -mm 2/3] nbd: nbd_thread_recv: remove the buggy kernel_dequeue_signal()
Quoted 7 lines · Markus Pargmann
Hi Oleg,
Quoted 2 lines · Oleg Nesterov
nbd_thread_recv()is called by userspace, it is very wrong to dequeue and throw out a signal.
Quoted 7 lines
This signal handling for a userspace process is implicitly implemented for several years already through the timeout handling. This is nothing new and could potentially break userspace if someone disconnects NBD using the kill command. As we expose the appropriate PID of the process as well this is possible to be used in an init script.
So I am not sure about this patch yet.
I strongly believe this kernel_dequeue_signal() must die, it is very wrong and I can't even enumerate all problems.
And why do you want it? Probably to "hide" the SIGKILL sent while this process was exposed as ->task_recv. This can not work even in the simplest case when this process is single-threaded. kernel_dequeue_signal() won't clear SIGNAL_GROUP_EXIT set by SIGKILL, it won't remove SIGKILL from shared_pending if it was sent by the kill command.
Note also that SIGKILL can be sent from another thread which does exec/group_exit/coredump. In this case the state of this thread group will be very wrong after kernel_dequeue_signal() removes SIGKILL from task_struct->pending.
Finally. We can not even know which signal we are going to dequeue and throw out. Say, it can be SIGCHLD or any other unrelated signal.
No, this can't be right.
Oleg.
PATCH 3/3 nbd: don't abuse irqsave/irqrestore while taking nbd->tasks_lock
In reply to Oleg NesterovBoth nbd_thread_recv() and nbd_thread_send() are might_sleep() and called with irqs enabled(), irqsave/irqrestore make no sense and imo look confusing.
--- drivers/block/nbd.c | 22 ++++++++++------------ 1 files changed, 10 insertions(+), 12 deletions(-)
drivers/block/nbd.c +10 -12
@@ -406,23 +406,22 @@ static int nbd_thread_recv(struct nbd_device *nbd) {struct request *req;int ret; -unsigned long flags;BUG_ON (nbd->magic !=NBD_MAGIC );sk_set_memalloc (nbd->sock->sk); -spin_lock_irqsave (&nbd->tasks_lock, flags); +spin_lock_irq (&nbd->tasks_lock); nbd->task_recv = current; -spin_unlock_irqrestore (&nbd->tasks_lock, flags); +spin_unlock_irq (&nbd->tasks_lock); ret =device_create_file (disk_to_dev (nbd->disk), &pid_attr);if (ret) {dev_err (disk_to_dev (nbd->disk),"device_create_file failed!\n" ); -spin_lock_irqsave (&nbd->tasks_lock, flags); +spin_lock_irq (&nbd->tasks_lock); nbd->task_recv =NULL ; -spin_unlock_irqrestore (&nbd->tasks_lock, flags); +spin_unlock_irq (&nbd->tasks_lock);return ret; }
@@ -439,9 +438,9 @@ static int nbd_thread_recv(struct nbd_device *nbd)device_remove_file (disk_to_dev (nbd->disk), &pid_attr); -spin_lock_irqsave (&nbd->tasks_lock, flags); +spin_lock_irq (&nbd->tasks_lock); nbd->task_recv =NULL ; -spin_unlock_irqrestore (&nbd->tasks_lock, flags); +spin_unlock_irq (&nbd->tasks_lock);if (signal_pending (current)) { dev_warn(nbd_to_dev(nbd), "pid %d, %s, got signal",
@@ -543,11 +542,10 @@ static int nbd_thread_send(void *data) {struct nbd_device *nbd = data;struct request *req; -unsigned long flags; -spin_lock_irqsave (&nbd->tasks_lock, flags); +spin_lock_irq (&nbd->tasks_lock); nbd->task_send = current; -spin_unlock_irqrestore (&nbd->tasks_lock, flags); +spin_unlock_irq (&nbd->tasks_lock);set_user_nice (current,MIN_NICE );while (!kthread_should_stop () || !list_empty (&nbd->waiting_queue)) {
@@ -581,9 +579,9 @@ static int nbd_thread_send(void *data)nbd_handle_req (nbd, req); } -spin_lock_irqsave (&nbd->tasks_lock, flags); +spin_lock_irq (&nbd->tasks_lock); nbd->task_send =NULL ; -spin_unlock_irqrestore (&nbd->tasks_lock, flags); +spin_unlock_irq (&nbd->tasks_lock);return 0 ; }
Signature · 1 line
1.5.5.1
Markus Pargmann
AppliedRe: [PATCH -mm 3/3] nbd: don't abuse irqsave/irqrestore while taking nbd->tasks_lock
Quoted 3 lines · Oleg Nesterov
Both
nbd_thread_recv()andnbd_thread_send()aremight_sleep()and called with irqsenabled(), irqsave/irqrestore make no sense and imo look confusing.
Thanks, applied.
Regards,
Markus
Quoted 80 lines
Signed-off-by Oleg Nesterov <[email protected]>--- drivers/block/nbd.c | 22 ++++++++++------------ 1 files changed, 10 insertions(+), 12 deletions(-)drivers/block/nbd.c +10
-12@@ -406,23 +406,22 @@ static int nbd_thread_recv(struct nbd_device *nbd) {struct request *req;int ret; -unsigned long flags;BUG_ON (nbd->magic !=NBD_MAGIC );sk_set_memalloc (nbd->sock->sk); -spin_lock_irqsave (&nbd->tasks_lock, flags); +spin_lock_irq (&nbd->tasks_lock); nbd->task_recv = current; -spin_unlock_irqrestore (&nbd->tasks_lock, flags); +spin_unlock_irq (&nbd->tasks_lock); ret =device_create_file (disk_to_dev (nbd->disk), &pid_attr);if (ret) {dev_err (disk_to_dev (nbd->disk),"device_create_file failed!\n" ); -spin_lock_irqsave (&nbd->tasks_lock, flags); +spin_lock_irq (&nbd->tasks_lock); nbd->task_recv =NULL ; -spin_unlock_irqrestore (&nbd->tasks_lock, flags); +spin_unlock_irq (&nbd->tasks_lock);return ret; }@@ -439,9 +438,9 @@ static int nbd_thread_recv(struct nbd_device *nbd)device_remove_file (disk_to_dev (nbd->disk), &pid_attr); -spin_lock_irqsave (&nbd->tasks_lock, flags); +spin_lock_irq (&nbd->tasks_lock); nbd->task_recv =NULL ; -spin_unlock_irqrestore (&nbd->tasks_lock, flags); +spin_unlock_irq (&nbd->tasks_lock);if (signal_pending (current)) { dev_warn(nbd_to_dev(nbd), "pid %d, %s, got signal",@@ -543,11 +542,10 @@ static int nbd_thread_send(void *data) {struct nbd_device *nbd = data;struct request *req; -unsigned long flags; -spin_lock_irqsave (&nbd->tasks_lock, flags); +spin_lock_irq (&nbd->tasks_lock); nbd->task_send = current; -spin_unlock_irqrestore (&nbd->tasks_lock, flags); +spin_unlock_irq (&nbd->tasks_lock);set_user_nice (current,MIN_NICE );while (!kthread_should_stop () || !list_empty (&nbd->waiting_queue)) {@@ -581,9 +579,9 @@ static int nbd_thread_send(void *data)nbd_handle_req (nbd, req); } -spin_lock_irqsave (&nbd->tasks_lock, flags); +spin_lock_irq (&nbd->tasks_lock); nbd->task_send =NULL ; -spin_unlock_irqrestore (&nbd->tasks_lock, flags); +spin_unlock_irq (&nbd->tasks_lock);return 0 ; }Signature · 1 line
1.5.5.1
Signature · 4 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |