Re: capable() during kernel init was Re: 2.1.111: Could not allocate TCP control block

Andrew Morgan (morgan@transmeta.com)
Thu, 30 Jul 1998 09:39:00 -0700


Andi,

I think we are agreed on the following fact: the capable() code, by
design, only makes sense for tasks. If the kernel is in a
pre-task-available state, then the capable call should not be made.

If it wasn't a bad idea, you could work around this problem with:

case SOCK_RAW:
if (!capable(CAP_NET_RAW))
goto free_and_badperm;
+ case _SOCK_RAW_INIT:
if (!protocol)

But this obviously suffers from the fact that this "internal"
sock->type is instantly available to user space.

Its not clear to me why the initialization needs to use the generic
capability filtered code sequence at all. Logically, we are
attempting to run before we can walk.

Since Linus wants things fast _and_ maintainable, I think I would
investigate delaying the initialization of the ip code until after the
current task has been properly initialized.

[$.02 from someone that's not to familiar with the kernel
initialization sequence. For all I know, this problem has already
been fixed ;^]

Cheers

Andrew

Andi Kleen writes:
> Date: Thu, 30 Jul 1998 00:14:09 +0200
> From: Andi Kleen <ak@muc.de>
> To: Andrew McGregor <andrew@indranet.co.nz>, Andi Kleen <ak@muc.de>,
> linux-kernel@vger.rutgers.edu
> Cc: morgan@transmeta.com, torvalds@transmeta.com
> Subject: capable() during kernel init was Re: 2.1.111: Could not allocate TCP control block
>
> [Andrew Morgan and Linus CC'ed]
>
> On Wed, Jul 29, 1998 at 06:47:49AM +0200, Andrew McGregor wrote:
> >
> >
> > Andi Kleen wrote:
> >
> > > Andrew McGregor <andrew@indranet.co.nz> writes:
> > >
> > > > (Please CC: me, as I read the digest form of the list and replying can be messy.)
> > > >
> > > >
> > > > I just compiled 2.1.111 (UP) and got this message when I tried to boot it:
> > > >
> > > > kernel panic: Could not allocate TCP control block
> > > >
> > > > upon which it hung, saying "in swapper task, not syncing.".
> > >
> > > My 2.1.111 kernel source does not contain this message. Did you really get
> > > this exact message, or do you use any non-standard modules?
> > >
> > > -Andi
> > >
> > >
> >
> > I didn't get that exact message, I relied on memory and got it wrong.
> > Here's the code which created it, from tcp_ipv4.c, the panic is line 1777:
> >
> > tcp_socket->inode = &tcp_inode;
> > tcp_socket->state = SS_UNCONNECTED;
> > tcp_socket->type=SOCK_RAW;
> >
> > if ((err=ops->create(tcp_socket, IPPROTO_TCP))<0)
> > panic("Failed to create the TCP control socket, err=%d.\n", err)
> > ;
> >
> > The err= etc. is mine, to help debug a bit further.
> > When I boot this it gives
> >
> > Failed to create the TCP control socket, err=-1.
> >
> > which is EPERM.
> >
> > As far as I can see, this comes from af_inet.c:inet_create lines 376-378:
> >
> > case SOCK_RAW:
> > if (!capable(CAP_NET_RAW))
> > goto free_and_badperm;
> >
> > which results in inet_create returning -EPERM, which is silly during bootup!
>
> Ok, the problem is clear now.
>
> capable is defined as:
>
> extern inline int capable(int cap)
> {
> if (cap_raised(current->cap_effective, cap))
>
>
> and sock_init() is called early in start_kernel() before current has any meaning. In most
> cases it happens to work anyways because there is the right junk on the bottom of the
> stack 8k segment, in your case it doesn't.
>
> Possible solutions:
> - Move sock_init() into init
> - Add a special in_kernel or in_init flag for this case.
>
> The special flag has the disadvantage that it is much harder to maintain in the long run
> (because testing it in the capable() inline would bloat the kernel, and adding it to all
> cases that might be called is hard and it is easy to miss one)
>
>
> Linus, what do you think?
>
>
> -Andi
>
>
>
>
>

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html