On 08/11, Eric W. Biederman wrote:
>
> --- a/kernel/fork.c
> +++ b/kernel/fork.c
> @@ -1866,13 +1866,17 @@ static int check_unshare_flags(unsigned long 
> unshare_flags)
>                               CLONE_NEWUSER|CLONE_NEWPID))
>               return -EINVAL;
>       /*
> -      * Not implemented, but pretend it works if there is nothing to
> -      * unshare. Note that unsharing CLONE_THREAD or CLONE_SIGHAND
> -      * needs to unshare vm.
> +      * Not implemented, but pretend it works if there is nothing
> +      * to unshare.  Note that unsharing the address space or the
> +      * signal handlers also need to unshare the signal queues (aka
> +      * CLONE_THREAD).
>        */
>       if (unshare_flags & (CLONE_THREAD | CLONE_SIGHAND | CLONE_VM)) {
> -             /* FIXME: get_task_mm() increments ->mm_users */
> -             if (atomic_read(&current->mm->mm_users) > 1)
> +             if (!thread_group_empty(current))
> +                     return -EINVAL;
> +     }
> +     if (unshare_flags & CLONE_VM) {
> +             if (!current_is_single_threaded())
>                       return -EINVAL;
>       }

OK, but then you can remove "| CLONE_VM" from the previous check...


> @@ -1941,16 +1945,16 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
>       if (unshare_flags & CLONE_NEWUSER)
>               unshare_flags |= CLONE_THREAD | CLONE_FS;
>       /*
> -      * If unsharing a thread from a thread group, must also unshare vm.
> -      */
> -     if (unshare_flags & CLONE_THREAD)
> -             unshare_flags |= CLONE_VM;

OK,

>       /*
> +      * If unsharing a signal handlers, must also unshare the signal queues.
> +      */
> +     if (unshare_flags & CLONE_SIGHAND)
> +             unshare_flags |= CLONE_THREAD;

This looks unnecessary, check_unshare_flags() checks "THREAD | SIGHAND".
And to me the comment looks misleading although I won't argue.

And in fact this doesn't look exactly right, or I am totally confused.
Shouldn't we do

        if (unshare_flags & CLONE_SIGHAND)
                unshare_flags |= CLONE_VM;

? Or change check_unshare_flags()...

Otherwise suppose that a single threaded process does clone(VM | SIGHAND)
and (say) child does sys_unshare(SIGHAND). This will wrongly succeed afaics.

Oleg.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to