Re: [PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy

2018-04-11 Thread Mickaël Salaün

On 04/10/2018 06:48 AM, Alexei Starovoitov wrote:
> On Mon, Apr 09, 2018 at 12:01:59AM +0200, Mickaël Salaün wrote:
>>
>> On 04/08/2018 11:06 PM, Andy Lutomirski wrote:
>>> On Sun, Apr 8, 2018 at 6:13 AM, Mickaël Salaün  wrote:

 On 02/27/2018 10:48 PM, Mickaël Salaün wrote:
>
> On 27/02/2018 17:39, Andy Lutomirski wrote:
>> On Tue, Feb 27, 2018 at 5:32 AM, Alexei Starovoitov
>>  wrote:
>>> On Tue, Feb 27, 2018 at 05:20:55AM +, Andy Lutomirski wrote:
 On Tue, Feb 27, 2018 at 4:54 AM, Alexei Starovoitov
  wrote:
> On Tue, Feb 27, 2018 at 04:40:34AM +, Andy Lutomirski wrote:
>> On Tue, Feb 27, 2018 at 2:08 AM, Alexei Starovoitov
>>  wrote:
>>> On Tue, Feb 27, 2018 at 01:41:15AM +0100, Mickaël Salaün wrote:
 The seccomp(2) syscall can be used by a task to apply a Landlock 
 program
 to itself. As a seccomp filter, a Landlock program is enforced for 
 the
 current task and all its future children. A program is immutable 
 and a
 task can only add new restricting programs to itself, forming a 
 list of
 programss.

 A Landlock program is tied to a Landlock hook. If the action on a 
 kernel
 object is allowed by the other Linux security mechanisms (e.g. DAC,
 capabilities, other LSM), then a Landlock hook related to this 
 kind of
 object is triggered. The list of programs for this hook is then
 evaluated. Each program return a 32-bit value which can deny the 
 action
 on a kernel object with a non-zero value. If every programs of the 
 list
 return zero, then the action on the object is allowed.

 Multiple Landlock programs can be chained to share a 64-bits value 
 for a
 call chain (e.g. evaluating multiple elements of a file path).  
 This
 chaining is restricted when a process construct this chain by 
 loading a
 program, but additional checks are performed when it requests to 
 apply
 this chain of programs to itself.  The restrictions ensure that it 
 is
 not possible to call multiple programs in a way that would imply to
 handle multiple shared values (i.e. cookies) for one chain.  For 
 now,
 only a fs_pick program can be chained to the same type of program,
 because it may make sense if they have different triggers (cf. next
 commits).  This restrictions still allows to reuse Landlock 
 programs in
 a safe way (e.g. use the same loaded fs_walk program with multiple
 chains of fs_pick programs).

 Signed-off-by: Mickaël Salaün 
>>>
>>> ...
>>>
 +struct landlock_prog_set *landlock_prepend_prog(
 + struct landlock_prog_set *current_prog_set,
 + struct bpf_prog *prog)
 +{
 + struct landlock_prog_set *new_prog_set = current_prog_set;
 + unsigned long pages;
 + int err;
 + size_t i;
 + struct landlock_prog_set tmp_prog_set = {};
 +
 + if (prog->type != BPF_PROG_TYPE_LANDLOCK_HOOK)
 + return ERR_PTR(-EINVAL);
 +
 + /* validate memory size allocation */
 + pages = prog->pages;
 + if (current_prog_set) {
 + size_t i;
 +
 + for (i = 0; i < 
 ARRAY_SIZE(current_prog_set->programs); i++) {
 + struct landlock_prog_list *walker_p;
 +
 + for (walker_p = 
 current_prog_set->programs[i];
 + walker_p; walker_p = 
 walker_p->prev)
 + pages += walker_p->prog->pages;
 + }
 + /* count a struct landlock_prog_set if we need to 
 allocate one */
 + if (refcount_read(_prog_set->usage) != 1)
 + pages += round_up(sizeof(*current_prog_set), 
 PAGE_SIZE)
 + / PAGE_SIZE;
 + }
 + if (pages > LANDLOCK_PROGRAMS_MAX_PAGES)
 + return ERR_PTR(-E2BIG);
 +
 + /* ensure early that we can allocate enough memory for the 
 new

Re: [PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy

2018-04-09 Thread Alexei Starovoitov
On Mon, Apr 09, 2018 at 12:01:59AM +0200, Mickaël Salaün wrote:
> 
> On 04/08/2018 11:06 PM, Andy Lutomirski wrote:
> > On Sun, Apr 8, 2018 at 6:13 AM, Mickaël Salaün  wrote:
> >>
> >> On 02/27/2018 10:48 PM, Mickaël Salaün wrote:
> >>>
> >>> On 27/02/2018 17:39, Andy Lutomirski wrote:
>  On Tue, Feb 27, 2018 at 5:32 AM, Alexei Starovoitov
>   wrote:
> > On Tue, Feb 27, 2018 at 05:20:55AM +, Andy Lutomirski wrote:
> >> On Tue, Feb 27, 2018 at 4:54 AM, Alexei Starovoitov
> >>  wrote:
> >>> On Tue, Feb 27, 2018 at 04:40:34AM +, Andy Lutomirski wrote:
>  On Tue, Feb 27, 2018 at 2:08 AM, Alexei Starovoitov
>   wrote:
> > On Tue, Feb 27, 2018 at 01:41:15AM +0100, Mickaël Salaün wrote:
> >> The seccomp(2) syscall can be used by a task to apply a Landlock 
> >> program
> >> to itself. As a seccomp filter, a Landlock program is enforced for 
> >> the
> >> current task and all its future children. A program is immutable 
> >> and a
> >> task can only add new restricting programs to itself, forming a 
> >> list of
> >> programss.
> >>
> >> A Landlock program is tied to a Landlock hook. If the action on a 
> >> kernel
> >> object is allowed by the other Linux security mechanisms (e.g. DAC,
> >> capabilities, other LSM), then a Landlock hook related to this 
> >> kind of
> >> object is triggered. The list of programs for this hook is then
> >> evaluated. Each program return a 32-bit value which can deny the 
> >> action
> >> on a kernel object with a non-zero value. If every programs of the 
> >> list
> >> return zero, then the action on the object is allowed.
> >>
> >> Multiple Landlock programs can be chained to share a 64-bits value 
> >> for a
> >> call chain (e.g. evaluating multiple elements of a file path).  
> >> This
> >> chaining is restricted when a process construct this chain by 
> >> loading a
> >> program, but additional checks are performed when it requests to 
> >> apply
> >> this chain of programs to itself.  The restrictions ensure that it 
> >> is
> >> not possible to call multiple programs in a way that would imply to
> >> handle multiple shared values (i.e. cookies) for one chain.  For 
> >> now,
> >> only a fs_pick program can be chained to the same type of program,
> >> because it may make sense if they have different triggers (cf. next
> >> commits).  This restrictions still allows to reuse Landlock 
> >> programs in
> >> a safe way (e.g. use the same loaded fs_walk program with multiple
> >> chains of fs_pick programs).
> >>
> >> Signed-off-by: Mickaël Salaün 
> >
> > ...
> >
> >> +struct landlock_prog_set *landlock_prepend_prog(
> >> + struct landlock_prog_set *current_prog_set,
> >> + struct bpf_prog *prog)
> >> +{
> >> + struct landlock_prog_set *new_prog_set = current_prog_set;
> >> + unsigned long pages;
> >> + int err;
> >> + size_t i;
> >> + struct landlock_prog_set tmp_prog_set = {};
> >> +
> >> + if (prog->type != BPF_PROG_TYPE_LANDLOCK_HOOK)
> >> + return ERR_PTR(-EINVAL);
> >> +
> >> + /* validate memory size allocation */
> >> + pages = prog->pages;
> >> + if (current_prog_set) {
> >> + size_t i;
> >> +
> >> + for (i = 0; i < 
> >> ARRAY_SIZE(current_prog_set->programs); i++) {
> >> + struct landlock_prog_list *walker_p;
> >> +
> >> + for (walker_p = 
> >> current_prog_set->programs[i];
> >> + walker_p; walker_p = 
> >> walker_p->prev)
> >> + pages += walker_p->prog->pages;
> >> + }
> >> + /* count a struct landlock_prog_set if we need to 
> >> allocate one */
> >> + if (refcount_read(_prog_set->usage) != 1)
> >> + pages += round_up(sizeof(*current_prog_set), 
> >> PAGE_SIZE)
> >> + / PAGE_SIZE;
> >> + }
> >> + if (pages > LANDLOCK_PROGRAMS_MAX_PAGES)
> >> + return ERR_PTR(-E2BIG);
> >> +
> >> + /* ensure early that we can allocate enough memory for the 
> >> new
> >> +  * prog_lists */
> >> + err = 

Re: [PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy

2018-04-08 Thread Mickaël Salaün

On 04/08/2018 11:06 PM, Andy Lutomirski wrote:
> On Sun, Apr 8, 2018 at 6:13 AM, Mickaël Salaün  wrote:
>>
>> On 02/27/2018 10:48 PM, Mickaël Salaün wrote:
>>>
>>> On 27/02/2018 17:39, Andy Lutomirski wrote:
 On Tue, Feb 27, 2018 at 5:32 AM, Alexei Starovoitov
  wrote:
> On Tue, Feb 27, 2018 at 05:20:55AM +, Andy Lutomirski wrote:
>> On Tue, Feb 27, 2018 at 4:54 AM, Alexei Starovoitov
>>  wrote:
>>> On Tue, Feb 27, 2018 at 04:40:34AM +, Andy Lutomirski wrote:
 On Tue, Feb 27, 2018 at 2:08 AM, Alexei Starovoitov
  wrote:
> On Tue, Feb 27, 2018 at 01:41:15AM +0100, Mickaël Salaün wrote:
>> The seccomp(2) syscall can be used by a task to apply a Landlock 
>> program
>> to itself. As a seccomp filter, a Landlock program is enforced for 
>> the
>> current task and all its future children. A program is immutable and 
>> a
>> task can only add new restricting programs to itself, forming a list 
>> of
>> programss.
>>
>> A Landlock program is tied to a Landlock hook. If the action on a 
>> kernel
>> object is allowed by the other Linux security mechanisms (e.g. DAC,
>> capabilities, other LSM), then a Landlock hook related to this kind 
>> of
>> object is triggered. The list of programs for this hook is then
>> evaluated. Each program return a 32-bit value which can deny the 
>> action
>> on a kernel object with a non-zero value. If every programs of the 
>> list
>> return zero, then the action on the object is allowed.
>>
>> Multiple Landlock programs can be chained to share a 64-bits value 
>> for a
>> call chain (e.g. evaluating multiple elements of a file path).  This
>> chaining is restricted when a process construct this chain by 
>> loading a
>> program, but additional checks are performed when it requests to 
>> apply
>> this chain of programs to itself.  The restrictions ensure that it is
>> not possible to call multiple programs in a way that would imply to
>> handle multiple shared values (i.e. cookies) for one chain.  For now,
>> only a fs_pick program can be chained to the same type of program,
>> because it may make sense if they have different triggers (cf. next
>> commits).  This restrictions still allows to reuse Landlock programs 
>> in
>> a safe way (e.g. use the same loaded fs_walk program with multiple
>> chains of fs_pick programs).
>>
>> Signed-off-by: Mickaël Salaün 
>
> ...
>
>> +struct landlock_prog_set *landlock_prepend_prog(
>> + struct landlock_prog_set *current_prog_set,
>> + struct bpf_prog *prog)
>> +{
>> + struct landlock_prog_set *new_prog_set = current_prog_set;
>> + unsigned long pages;
>> + int err;
>> + size_t i;
>> + struct landlock_prog_set tmp_prog_set = {};
>> +
>> + if (prog->type != BPF_PROG_TYPE_LANDLOCK_HOOK)
>> + return ERR_PTR(-EINVAL);
>> +
>> + /* validate memory size allocation */
>> + pages = prog->pages;
>> + if (current_prog_set) {
>> + size_t i;
>> +
>> + for (i = 0; i < 
>> ARRAY_SIZE(current_prog_set->programs); i++) {
>> + struct landlock_prog_list *walker_p;
>> +
>> + for (walker_p = current_prog_set->programs[i];
>> + walker_p; walker_p = 
>> walker_p->prev)
>> + pages += walker_p->prog->pages;
>> + }
>> + /* count a struct landlock_prog_set if we need to 
>> allocate one */
>> + if (refcount_read(_prog_set->usage) != 1)
>> + pages += round_up(sizeof(*current_prog_set), 
>> PAGE_SIZE)
>> + / PAGE_SIZE;
>> + }
>> + if (pages > LANDLOCK_PROGRAMS_MAX_PAGES)
>> + return ERR_PTR(-E2BIG);
>> +
>> + /* ensure early that we can allocate enough memory for the new
>> +  * prog_lists */
>> + err = store_landlock_prog(_prog_set, current_prog_set, 
>> prog);
>> + if (err)
>> + return ERR_PTR(err);
>> +
>> + /*
>> +  * Each task_struct points to an array of prog list pointers.  
>> These
>> +  * tables are duplicated when additions are 

Re: [PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy

2018-04-08 Thread Andy Lutomirski
On Sun, Apr 8, 2018 at 6:13 AM, Mickaël Salaün  wrote:
>
> On 02/27/2018 10:48 PM, Mickaël Salaün wrote:
>>
>> On 27/02/2018 17:39, Andy Lutomirski wrote:
>>> On Tue, Feb 27, 2018 at 5:32 AM, Alexei Starovoitov
>>>  wrote:
 On Tue, Feb 27, 2018 at 05:20:55AM +, Andy Lutomirski wrote:
> On Tue, Feb 27, 2018 at 4:54 AM, Alexei Starovoitov
>  wrote:
>> On Tue, Feb 27, 2018 at 04:40:34AM +, Andy Lutomirski wrote:
>>> On Tue, Feb 27, 2018 at 2:08 AM, Alexei Starovoitov
>>>  wrote:
 On Tue, Feb 27, 2018 at 01:41:15AM +0100, Mickaël Salaün wrote:
> The seccomp(2) syscall can be used by a task to apply a Landlock 
> program
> to itself. As a seccomp filter, a Landlock program is enforced for the
> current task and all its future children. A program is immutable and a
> task can only add new restricting programs to itself, forming a list 
> of
> programss.
>
> A Landlock program is tied to a Landlock hook. If the action on a 
> kernel
> object is allowed by the other Linux security mechanisms (e.g. DAC,
> capabilities, other LSM), then a Landlock hook related to this kind of
> object is triggered. The list of programs for this hook is then
> evaluated. Each program return a 32-bit value which can deny the 
> action
> on a kernel object with a non-zero value. If every programs of the 
> list
> return zero, then the action on the object is allowed.
>
> Multiple Landlock programs can be chained to share a 64-bits value 
> for a
> call chain (e.g. evaluating multiple elements of a file path).  This
> chaining is restricted when a process construct this chain by loading 
> a
> program, but additional checks are performed when it requests to apply
> this chain of programs to itself.  The restrictions ensure that it is
> not possible to call multiple programs in a way that would imply to
> handle multiple shared values (i.e. cookies) for one chain.  For now,
> only a fs_pick program can be chained to the same type of program,
> because it may make sense if they have different triggers (cf. next
> commits).  This restrictions still allows to reuse Landlock programs 
> in
> a safe way (e.g. use the same loaded fs_walk program with multiple
> chains of fs_pick programs).
>
> Signed-off-by: Mickaël Salaün 

 ...

> +struct landlock_prog_set *landlock_prepend_prog(
> + struct landlock_prog_set *current_prog_set,
> + struct bpf_prog *prog)
> +{
> + struct landlock_prog_set *new_prog_set = current_prog_set;
> + unsigned long pages;
> + int err;
> + size_t i;
> + struct landlock_prog_set tmp_prog_set = {};
> +
> + if (prog->type != BPF_PROG_TYPE_LANDLOCK_HOOK)
> + return ERR_PTR(-EINVAL);
> +
> + /* validate memory size allocation */
> + pages = prog->pages;
> + if (current_prog_set) {
> + size_t i;
> +
> + for (i = 0; i < ARRAY_SIZE(current_prog_set->programs); 
> i++) {
> + struct landlock_prog_list *walker_p;
> +
> + for (walker_p = current_prog_set->programs[i];
> + walker_p; walker_p = 
> walker_p->prev)
> + pages += walker_p->prog->pages;
> + }
> + /* count a struct landlock_prog_set if we need to 
> allocate one */
> + if (refcount_read(_prog_set->usage) != 1)
> + pages += round_up(sizeof(*current_prog_set), 
> PAGE_SIZE)
> + / PAGE_SIZE;
> + }
> + if (pages > LANDLOCK_PROGRAMS_MAX_PAGES)
> + return ERR_PTR(-E2BIG);
> +
> + /* ensure early that we can allocate enough memory for the new
> +  * prog_lists */
> + err = store_landlock_prog(_prog_set, current_prog_set, 
> prog);
> + if (err)
> + return ERR_PTR(err);
> +
> + /*
> +  * Each task_struct points to an array of prog list pointers.  
> These
> +  * tables are duplicated when additions are made (which means 
> each
> +  * table needs to be refcounted for the processes using it). 
> When a new
> +  * table is created, all the refcounters on the 

Re: [PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy

2018-04-08 Thread Mickaël Salaün

On 02/27/2018 10:48 PM, Mickaël Salaün wrote:
> 
> On 27/02/2018 17:39, Andy Lutomirski wrote:
>> On Tue, Feb 27, 2018 at 5:32 AM, Alexei Starovoitov
>>  wrote:
>>> On Tue, Feb 27, 2018 at 05:20:55AM +, Andy Lutomirski wrote:
 On Tue, Feb 27, 2018 at 4:54 AM, Alexei Starovoitov
  wrote:
> On Tue, Feb 27, 2018 at 04:40:34AM +, Andy Lutomirski wrote:
>> On Tue, Feb 27, 2018 at 2:08 AM, Alexei Starovoitov
>>  wrote:
>>> On Tue, Feb 27, 2018 at 01:41:15AM +0100, Mickaël Salaün wrote:
 The seccomp(2) syscall can be used by a task to apply a Landlock 
 program
 to itself. As a seccomp filter, a Landlock program is enforced for the
 current task and all its future children. A program is immutable and a
 task can only add new restricting programs to itself, forming a list of
 programss.

 A Landlock program is tied to a Landlock hook. If the action on a 
 kernel
 object is allowed by the other Linux security mechanisms (e.g. DAC,
 capabilities, other LSM), then a Landlock hook related to this kind of
 object is triggered. The list of programs for this hook is then
 evaluated. Each program return a 32-bit value which can deny the action
 on a kernel object with a non-zero value. If every programs of the list
 return zero, then the action on the object is allowed.

 Multiple Landlock programs can be chained to share a 64-bits value for 
 a
 call chain (e.g. evaluating multiple elements of a file path).  This
 chaining is restricted when a process construct this chain by loading a
 program, but additional checks are performed when it requests to apply
 this chain of programs to itself.  The restrictions ensure that it is
 not possible to call multiple programs in a way that would imply to
 handle multiple shared values (i.e. cookies) for one chain.  For now,
 only a fs_pick program can be chained to the same type of program,
 because it may make sense if they have different triggers (cf. next
 commits).  This restrictions still allows to reuse Landlock programs in
 a safe way (e.g. use the same loaded fs_walk program with multiple
 chains of fs_pick programs).

 Signed-off-by: Mickaël Salaün 
>>>
>>> ...
>>>
 +struct landlock_prog_set *landlock_prepend_prog(
 + struct landlock_prog_set *current_prog_set,
 + struct bpf_prog *prog)
 +{
 + struct landlock_prog_set *new_prog_set = current_prog_set;
 + unsigned long pages;
 + int err;
 + size_t i;
 + struct landlock_prog_set tmp_prog_set = {};
 +
 + if (prog->type != BPF_PROG_TYPE_LANDLOCK_HOOK)
 + return ERR_PTR(-EINVAL);
 +
 + /* validate memory size allocation */
 + pages = prog->pages;
 + if (current_prog_set) {
 + size_t i;
 +
 + for (i = 0; i < ARRAY_SIZE(current_prog_set->programs); 
 i++) {
 + struct landlock_prog_list *walker_p;
 +
 + for (walker_p = current_prog_set->programs[i];
 + walker_p; walker_p = 
 walker_p->prev)
 + pages += walker_p->prog->pages;
 + }
 + /* count a struct landlock_prog_set if we need to 
 allocate one */
 + if (refcount_read(_prog_set->usage) != 1)
 + pages += round_up(sizeof(*current_prog_set), 
 PAGE_SIZE)
 + / PAGE_SIZE;
 + }
 + if (pages > LANDLOCK_PROGRAMS_MAX_PAGES)
 + return ERR_PTR(-E2BIG);
 +
 + /* ensure early that we can allocate enough memory for the new
 +  * prog_lists */
 + err = store_landlock_prog(_prog_set, current_prog_set, prog);
 + if (err)
 + return ERR_PTR(err);
 +
 + /*
 +  * Each task_struct points to an array of prog list pointers.  
 These
 +  * tables are duplicated when additions are made (which means 
 each
 +  * table needs to be refcounted for the processes using it). 
 When a new
 +  * table is created, all the refcounters on the prog_list are 
 bumped (to
 +  * track each table that references the prog). When a new prog is
 +  * added, it's just prepended to the list for the new table to 
 point
 +  * at.

Re: [PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy

2018-02-27 Thread Mickaël Salaün

On 27/02/2018 17:39, Andy Lutomirski wrote:
> On Tue, Feb 27, 2018 at 5:32 AM, Alexei Starovoitov
>  wrote:
>> On Tue, Feb 27, 2018 at 05:20:55AM +, Andy Lutomirski wrote:
>>> On Tue, Feb 27, 2018 at 4:54 AM, Alexei Starovoitov
>>>  wrote:
 On Tue, Feb 27, 2018 at 04:40:34AM +, Andy Lutomirski wrote:
> On Tue, Feb 27, 2018 at 2:08 AM, Alexei Starovoitov
>  wrote:
>> On Tue, Feb 27, 2018 at 01:41:15AM +0100, Mickaël Salaün wrote:
>>> The seccomp(2) syscall can be used by a task to apply a Landlock program
>>> to itself. As a seccomp filter, a Landlock program is enforced for the
>>> current task and all its future children. A program is immutable and a
>>> task can only add new restricting programs to itself, forming a list of
>>> programss.
>>>
>>> A Landlock program is tied to a Landlock hook. If the action on a kernel
>>> object is allowed by the other Linux security mechanisms (e.g. DAC,
>>> capabilities, other LSM), then a Landlock hook related to this kind of
>>> object is triggered. The list of programs for this hook is then
>>> evaluated. Each program return a 32-bit value which can deny the action
>>> on a kernel object with a non-zero value. If every programs of the list
>>> return zero, then the action on the object is allowed.
>>>
>>> Multiple Landlock programs can be chained to share a 64-bits value for a
>>> call chain (e.g. evaluating multiple elements of a file path).  This
>>> chaining is restricted when a process construct this chain by loading a
>>> program, but additional checks are performed when it requests to apply
>>> this chain of programs to itself.  The restrictions ensure that it is
>>> not possible to call multiple programs in a way that would imply to
>>> handle multiple shared values (i.e. cookies) for one chain.  For now,
>>> only a fs_pick program can be chained to the same type of program,
>>> because it may make sense if they have different triggers (cf. next
>>> commits).  This restrictions still allows to reuse Landlock programs in
>>> a safe way (e.g. use the same loaded fs_walk program with multiple
>>> chains of fs_pick programs).
>>>
>>> Signed-off-by: Mickaël Salaün 
>>
>> ...
>>
>>> +struct landlock_prog_set *landlock_prepend_prog(
>>> + struct landlock_prog_set *current_prog_set,
>>> + struct bpf_prog *prog)
>>> +{
>>> + struct landlock_prog_set *new_prog_set = current_prog_set;
>>> + unsigned long pages;
>>> + int err;
>>> + size_t i;
>>> + struct landlock_prog_set tmp_prog_set = {};
>>> +
>>> + if (prog->type != BPF_PROG_TYPE_LANDLOCK_HOOK)
>>> + return ERR_PTR(-EINVAL);
>>> +
>>> + /* validate memory size allocation */
>>> + pages = prog->pages;
>>> + if (current_prog_set) {
>>> + size_t i;
>>> +
>>> + for (i = 0; i < ARRAY_SIZE(current_prog_set->programs); 
>>> i++) {
>>> + struct landlock_prog_list *walker_p;
>>> +
>>> + for (walker_p = current_prog_set->programs[i];
>>> + walker_p; walker_p = 
>>> walker_p->prev)
>>> + pages += walker_p->prog->pages;
>>> + }
>>> + /* count a struct landlock_prog_set if we need to 
>>> allocate one */
>>> + if (refcount_read(_prog_set->usage) != 1)
>>> + pages += round_up(sizeof(*current_prog_set), 
>>> PAGE_SIZE)
>>> + / PAGE_SIZE;
>>> + }
>>> + if (pages > LANDLOCK_PROGRAMS_MAX_PAGES)
>>> + return ERR_PTR(-E2BIG);
>>> +
>>> + /* ensure early that we can allocate enough memory for the new
>>> +  * prog_lists */
>>> + err = store_landlock_prog(_prog_set, current_prog_set, prog);
>>> + if (err)
>>> + return ERR_PTR(err);
>>> +
>>> + /*
>>> +  * Each task_struct points to an array of prog list pointers.  
>>> These
>>> +  * tables are duplicated when additions are made (which means each
>>> +  * table needs to be refcounted for the processes using it). When 
>>> a new
>>> +  * table is created, all the refcounters on the prog_list are 
>>> bumped (to
>>> +  * track each table that references the prog). When a new prog is
>>> +  * added, it's just prepended to the list for the new table to 
>>> point
>>> +  * at.
>>> +  *
>>> +  * Manage all the possible errors before this step to not 
>>> uselessly
>>> +  * duplicate current_prog_set and avoid a rollback.
>>> +  */

Re: [PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy

2018-02-27 Thread Casey Schaufler
On 2/27/2018 9:36 AM, Andy Lutomirski wrote:
> On Tue, Feb 27, 2018 at 5:30 PM, Casey Schaufler  
> wrote:
>> On 2/27/2018 8:39 AM, Andy Lutomirski wrote:
>>> On Tue, Feb 27, 2018 at 5:32 AM, Alexei Starovoitov
>>>  wrote:
 [ Snip ]
>>> An earlier version of the patch set used the seccomp filter chain.
>>> Mickaël, what exactly was wrong with that approach other than that the
>>> seccomp() syscall was awkward for you to use?  You could add a
>>> seccomp_add_landlock_rule() syscall if you needed to.
>>>
>>> As a side comment, why is this an LSM at all, let alone a non-stacking
>>> LSM?  It would make a lot more sense to me to make Landlock depend on
>>> having LSMs configured in but to call the landlock hooks directly from
>>> the security_xyz() hooks.
>> Please, no. It is my serious intention to have at least the
>> infrastructure blob management in within a release or two, and
>> I think that's all Landlock needs. The security_xyz() hooks are
>> sufficiently hackish as it is without unnecessarily adding more
>> special cases.
>>
>>
> What do you mean by "infrastructure blob management"?

Today each security module manages their own module specific data,
for example inode->i_security and file->f_security. This prevents
having two security modules that have inode or file data from being
used at the same time, because they both need to manage those fields.
Moving the management of the module specific data (aka "blobs") from
the security modules to the module infrastructure will allow those
modules to coexist. Restrictions apply, of course, but I don't think
that Landlock uses any of the facilities that would have issues.



Re: [PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy

2018-02-27 Thread Andy Lutomirski
On Tue, Feb 27, 2018 at 5:30 PM, Casey Schaufler  wrote:
> On 2/27/2018 8:39 AM, Andy Lutomirski wrote:
>> On Tue, Feb 27, 2018 at 5:32 AM, Alexei Starovoitov
>>  wrote:
>>> [ Snip ]
>> An earlier version of the patch set used the seccomp filter chain.
>> Mickaël, what exactly was wrong with that approach other than that the
>> seccomp() syscall was awkward for you to use?  You could add a
>> seccomp_add_landlock_rule() syscall if you needed to.
>>
>> As a side comment, why is this an LSM at all, let alone a non-stacking
>> LSM?  It would make a lot more sense to me to make Landlock depend on
>> having LSMs configured in but to call the landlock hooks directly from
>> the security_xyz() hooks.
>
> Please, no. It is my serious intention to have at least the
> infrastructure blob management in within a release or two, and
> I think that's all Landlock needs. The security_xyz() hooks are
> sufficiently hackish as it is without unnecessarily adding more
> special cases.
>
>

What do you mean by "infrastructure blob management"?


Re: [PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy

2018-02-27 Thread Casey Schaufler
On 2/27/2018 8:39 AM, Andy Lutomirski wrote:
> On Tue, Feb 27, 2018 at 5:32 AM, Alexei Starovoitov
>  wrote:
>> [ Snip ]
> An earlier version of the patch set used the seccomp filter chain.
> Mickaël, what exactly was wrong with that approach other than that the
> seccomp() syscall was awkward for you to use?  You could add a
> seccomp_add_landlock_rule() syscall if you needed to.
>
> As a side comment, why is this an LSM at all, let alone a non-stacking
> LSM?  It would make a lot more sense to me to make Landlock depend on
> having LSMs configured in but to call the landlock hooks directly from
> the security_xyz() hooks.

Please, no. It is my serious intention to have at least the
infrastructure blob management in within a release or two, and
I think that's all Landlock needs. The security_xyz() hooks are
sufficiently hackish as it is without unnecessarily adding more
special cases.




Re: [PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy

2018-02-27 Thread Andy Lutomirski
On Tue, Feb 27, 2018 at 5:32 AM, Alexei Starovoitov
 wrote:
> On Tue, Feb 27, 2018 at 05:20:55AM +, Andy Lutomirski wrote:
>> On Tue, Feb 27, 2018 at 4:54 AM, Alexei Starovoitov
>>  wrote:
>> > On Tue, Feb 27, 2018 at 04:40:34AM +, Andy Lutomirski wrote:
>> >> On Tue, Feb 27, 2018 at 2:08 AM, Alexei Starovoitov
>> >>  wrote:
>> >> > On Tue, Feb 27, 2018 at 01:41:15AM +0100, Mickaël Salaün wrote:
>> >> >> The seccomp(2) syscall can be used by a task to apply a Landlock 
>> >> >> program
>> >> >> to itself. As a seccomp filter, a Landlock program is enforced for the
>> >> >> current task and all its future children. A program is immutable and a
>> >> >> task can only add new restricting programs to itself, forming a list of
>> >> >> programss.
>> >> >>
>> >> >> A Landlock program is tied to a Landlock hook. If the action on a 
>> >> >> kernel
>> >> >> object is allowed by the other Linux security mechanisms (e.g. DAC,
>> >> >> capabilities, other LSM), then a Landlock hook related to this kind of
>> >> >> object is triggered. The list of programs for this hook is then
>> >> >> evaluated. Each program return a 32-bit value which can deny the action
>> >> >> on a kernel object with a non-zero value. If every programs of the list
>> >> >> return zero, then the action on the object is allowed.
>> >> >>
>> >> >> Multiple Landlock programs can be chained to share a 64-bits value for 
>> >> >> a
>> >> >> call chain (e.g. evaluating multiple elements of a file path).  This
>> >> >> chaining is restricted when a process construct this chain by loading a
>> >> >> program, but additional checks are performed when it requests to apply
>> >> >> this chain of programs to itself.  The restrictions ensure that it is
>> >> >> not possible to call multiple programs in a way that would imply to
>> >> >> handle multiple shared values (i.e. cookies) for one chain.  For now,
>> >> >> only a fs_pick program can be chained to the same type of program,
>> >> >> because it may make sense if they have different triggers (cf. next
>> >> >> commits).  This restrictions still allows to reuse Landlock programs in
>> >> >> a safe way (e.g. use the same loaded fs_walk program with multiple
>> >> >> chains of fs_pick programs).
>> >> >>
>> >> >> Signed-off-by: Mickaël Salaün 
>> >> >
>> >> > ...
>> >> >
>> >> >> +struct landlock_prog_set *landlock_prepend_prog(
>> >> >> + struct landlock_prog_set *current_prog_set,
>> >> >> + struct bpf_prog *prog)
>> >> >> +{
>> >> >> + struct landlock_prog_set *new_prog_set = current_prog_set;
>> >> >> + unsigned long pages;
>> >> >> + int err;
>> >> >> + size_t i;
>> >> >> + struct landlock_prog_set tmp_prog_set = {};
>> >> >> +
>> >> >> + if (prog->type != BPF_PROG_TYPE_LANDLOCK_HOOK)
>> >> >> + return ERR_PTR(-EINVAL);
>> >> >> +
>> >> >> + /* validate memory size allocation */
>> >> >> + pages = prog->pages;
>> >> >> + if (current_prog_set) {
>> >> >> + size_t i;
>> >> >> +
>> >> >> + for (i = 0; i < ARRAY_SIZE(current_prog_set->programs); 
>> >> >> i++) {
>> >> >> + struct landlock_prog_list *walker_p;
>> >> >> +
>> >> >> + for (walker_p = current_prog_set->programs[i];
>> >> >> + walker_p; walker_p = 
>> >> >> walker_p->prev)
>> >> >> + pages += walker_p->prog->pages;
>> >> >> + }
>> >> >> + /* count a struct landlock_prog_set if we need to 
>> >> >> allocate one */
>> >> >> + if (refcount_read(_prog_set->usage) != 1)
>> >> >> + pages += round_up(sizeof(*current_prog_set), 
>> >> >> PAGE_SIZE)
>> >> >> + / PAGE_SIZE;
>> >> >> + }
>> >> >> + if (pages > LANDLOCK_PROGRAMS_MAX_PAGES)
>> >> >> + return ERR_PTR(-E2BIG);
>> >> >> +
>> >> >> + /* ensure early that we can allocate enough memory for the new
>> >> >> +  * prog_lists */
>> >> >> + err = store_landlock_prog(_prog_set, current_prog_set, prog);
>> >> >> + if (err)
>> >> >> + return ERR_PTR(err);
>> >> >> +
>> >> >> + /*
>> >> >> +  * Each task_struct points to an array of prog list pointers.  
>> >> >> These
>> >> >> +  * tables are duplicated when additions are made (which means 
>> >> >> each
>> >> >> +  * table needs to be refcounted for the processes using it). 
>> >> >> When a new
>> >> >> +  * table is created, all the refcounters on the prog_list are 
>> >> >> bumped (to
>> >> >> +  * track each table that references the prog). When a new prog is
>> >> >> +  * added, it's just prepended to the list for the new table to 
>> >> >> point
>> >> >> +  * at.
>> >> >> +  *
>> >> >> +  * Manage all the possible errors before this step to not 
>> >> >> uselessly
>> >> 

Re: [PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy

2018-02-26 Thread Alexei Starovoitov
On Tue, Feb 27, 2018 at 05:20:55AM +, Andy Lutomirski wrote:
> On Tue, Feb 27, 2018 at 4:54 AM, Alexei Starovoitov
>  wrote:
> > On Tue, Feb 27, 2018 at 04:40:34AM +, Andy Lutomirski wrote:
> >> On Tue, Feb 27, 2018 at 2:08 AM, Alexei Starovoitov
> >>  wrote:
> >> > On Tue, Feb 27, 2018 at 01:41:15AM +0100, Mickaël Salaün wrote:
> >> >> The seccomp(2) syscall can be used by a task to apply a Landlock program
> >> >> to itself. As a seccomp filter, a Landlock program is enforced for the
> >> >> current task and all its future children. A program is immutable and a
> >> >> task can only add new restricting programs to itself, forming a list of
> >> >> programss.
> >> >>
> >> >> A Landlock program is tied to a Landlock hook. If the action on a kernel
> >> >> object is allowed by the other Linux security mechanisms (e.g. DAC,
> >> >> capabilities, other LSM), then a Landlock hook related to this kind of
> >> >> object is triggered. The list of programs for this hook is then
> >> >> evaluated. Each program return a 32-bit value which can deny the action
> >> >> on a kernel object with a non-zero value. If every programs of the list
> >> >> return zero, then the action on the object is allowed.
> >> >>
> >> >> Multiple Landlock programs can be chained to share a 64-bits value for a
> >> >> call chain (e.g. evaluating multiple elements of a file path).  This
> >> >> chaining is restricted when a process construct this chain by loading a
> >> >> program, but additional checks are performed when it requests to apply
> >> >> this chain of programs to itself.  The restrictions ensure that it is
> >> >> not possible to call multiple programs in a way that would imply to
> >> >> handle multiple shared values (i.e. cookies) for one chain.  For now,
> >> >> only a fs_pick program can be chained to the same type of program,
> >> >> because it may make sense if they have different triggers (cf. next
> >> >> commits).  This restrictions still allows to reuse Landlock programs in
> >> >> a safe way (e.g. use the same loaded fs_walk program with multiple
> >> >> chains of fs_pick programs).
> >> >>
> >> >> Signed-off-by: Mickaël Salaün 
> >> >
> >> > ...
> >> >
> >> >> +struct landlock_prog_set *landlock_prepend_prog(
> >> >> + struct landlock_prog_set *current_prog_set,
> >> >> + struct bpf_prog *prog)
> >> >> +{
> >> >> + struct landlock_prog_set *new_prog_set = current_prog_set;
> >> >> + unsigned long pages;
> >> >> + int err;
> >> >> + size_t i;
> >> >> + struct landlock_prog_set tmp_prog_set = {};
> >> >> +
> >> >> + if (prog->type != BPF_PROG_TYPE_LANDLOCK_HOOK)
> >> >> + return ERR_PTR(-EINVAL);
> >> >> +
> >> >> + /* validate memory size allocation */
> >> >> + pages = prog->pages;
> >> >> + if (current_prog_set) {
> >> >> + size_t i;
> >> >> +
> >> >> + for (i = 0; i < ARRAY_SIZE(current_prog_set->programs); 
> >> >> i++) {
> >> >> + struct landlock_prog_list *walker_p;
> >> >> +
> >> >> + for (walker_p = current_prog_set->programs[i];
> >> >> + walker_p; walker_p = 
> >> >> walker_p->prev)
> >> >> + pages += walker_p->prog->pages;
> >> >> + }
> >> >> + /* count a struct landlock_prog_set if we need to 
> >> >> allocate one */
> >> >> + if (refcount_read(_prog_set->usage) != 1)
> >> >> + pages += round_up(sizeof(*current_prog_set), 
> >> >> PAGE_SIZE)
> >> >> + / PAGE_SIZE;
> >> >> + }
> >> >> + if (pages > LANDLOCK_PROGRAMS_MAX_PAGES)
> >> >> + return ERR_PTR(-E2BIG);
> >> >> +
> >> >> + /* ensure early that we can allocate enough memory for the new
> >> >> +  * prog_lists */
> >> >> + err = store_landlock_prog(_prog_set, current_prog_set, prog);
> >> >> + if (err)
> >> >> + return ERR_PTR(err);
> >> >> +
> >> >> + /*
> >> >> +  * Each task_struct points to an array of prog list pointers.  
> >> >> These
> >> >> +  * tables are duplicated when additions are made (which means each
> >> >> +  * table needs to be refcounted for the processes using it). When 
> >> >> a new
> >> >> +  * table is created, all the refcounters on the prog_list are 
> >> >> bumped (to
> >> >> +  * track each table that references the prog). When a new prog is
> >> >> +  * added, it's just prepended to the list for the new table to 
> >> >> point
> >> >> +  * at.
> >> >> +  *
> >> >> +  * Manage all the possible errors before this step to not 
> >> >> uselessly
> >> >> +  * duplicate current_prog_set and avoid a rollback.
> >> >> +  */
> >> >> + if (!new_prog_set) {
> >> >> + /*
> >> >> +  * If there is no Landlock program set used by the 
> >> >> current 

Re: [PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy

2018-02-26 Thread Andy Lutomirski
On Tue, Feb 27, 2018 at 4:54 AM, Alexei Starovoitov
 wrote:
> On Tue, Feb 27, 2018 at 04:40:34AM +, Andy Lutomirski wrote:
>> On Tue, Feb 27, 2018 at 2:08 AM, Alexei Starovoitov
>>  wrote:
>> > On Tue, Feb 27, 2018 at 01:41:15AM +0100, Mickaël Salaün wrote:
>> >> The seccomp(2) syscall can be used by a task to apply a Landlock program
>> >> to itself. As a seccomp filter, a Landlock program is enforced for the
>> >> current task and all its future children. A program is immutable and a
>> >> task can only add new restricting programs to itself, forming a list of
>> >> programss.
>> >>
>> >> A Landlock program is tied to a Landlock hook. If the action on a kernel
>> >> object is allowed by the other Linux security mechanisms (e.g. DAC,
>> >> capabilities, other LSM), then a Landlock hook related to this kind of
>> >> object is triggered. The list of programs for this hook is then
>> >> evaluated. Each program return a 32-bit value which can deny the action
>> >> on a kernel object with a non-zero value. If every programs of the list
>> >> return zero, then the action on the object is allowed.
>> >>
>> >> Multiple Landlock programs can be chained to share a 64-bits value for a
>> >> call chain (e.g. evaluating multiple elements of a file path).  This
>> >> chaining is restricted when a process construct this chain by loading a
>> >> program, but additional checks are performed when it requests to apply
>> >> this chain of programs to itself.  The restrictions ensure that it is
>> >> not possible to call multiple programs in a way that would imply to
>> >> handle multiple shared values (i.e. cookies) for one chain.  For now,
>> >> only a fs_pick program can be chained to the same type of program,
>> >> because it may make sense if they have different triggers (cf. next
>> >> commits).  This restrictions still allows to reuse Landlock programs in
>> >> a safe way (e.g. use the same loaded fs_walk program with multiple
>> >> chains of fs_pick programs).
>> >>
>> >> Signed-off-by: Mickaël Salaün 
>> >
>> > ...
>> >
>> >> +struct landlock_prog_set *landlock_prepend_prog(
>> >> + struct landlock_prog_set *current_prog_set,
>> >> + struct bpf_prog *prog)
>> >> +{
>> >> + struct landlock_prog_set *new_prog_set = current_prog_set;
>> >> + unsigned long pages;
>> >> + int err;
>> >> + size_t i;
>> >> + struct landlock_prog_set tmp_prog_set = {};
>> >> +
>> >> + if (prog->type != BPF_PROG_TYPE_LANDLOCK_HOOK)
>> >> + return ERR_PTR(-EINVAL);
>> >> +
>> >> + /* validate memory size allocation */
>> >> + pages = prog->pages;
>> >> + if (current_prog_set) {
>> >> + size_t i;
>> >> +
>> >> + for (i = 0; i < ARRAY_SIZE(current_prog_set->programs); 
>> >> i++) {
>> >> + struct landlock_prog_list *walker_p;
>> >> +
>> >> + for (walker_p = current_prog_set->programs[i];
>> >> + walker_p; walker_p = walker_p->prev)
>> >> + pages += walker_p->prog->pages;
>> >> + }
>> >> + /* count a struct landlock_prog_set if we need to allocate 
>> >> one */
>> >> + if (refcount_read(_prog_set->usage) != 1)
>> >> + pages += round_up(sizeof(*current_prog_set), 
>> >> PAGE_SIZE)
>> >> + / PAGE_SIZE;
>> >> + }
>> >> + if (pages > LANDLOCK_PROGRAMS_MAX_PAGES)
>> >> + return ERR_PTR(-E2BIG);
>> >> +
>> >> + /* ensure early that we can allocate enough memory for the new
>> >> +  * prog_lists */
>> >> + err = store_landlock_prog(_prog_set, current_prog_set, prog);
>> >> + if (err)
>> >> + return ERR_PTR(err);
>> >> +
>> >> + /*
>> >> +  * Each task_struct points to an array of prog list pointers.  These
>> >> +  * tables are duplicated when additions are made (which means each
>> >> +  * table needs to be refcounted for the processes using it). When a 
>> >> new
>> >> +  * table is created, all the refcounters on the prog_list are 
>> >> bumped (to
>> >> +  * track each table that references the prog). When a new prog is
>> >> +  * added, it's just prepended to the list for the new table to point
>> >> +  * at.
>> >> +  *
>> >> +  * Manage all the possible errors before this step to not uselessly
>> >> +  * duplicate current_prog_set and avoid a rollback.
>> >> +  */
>> >> + if (!new_prog_set) {
>> >> + /*
>> >> +  * If there is no Landlock program set used by the current 
>> >> task,
>> >> +  * then create a new one.
>> >> +  */
>> >> + new_prog_set = new_landlock_prog_set();
>> >> + if (IS_ERR(new_prog_set))
>> >> + goto put_tmp_lists;
>> >> + } else if (refcount_read(_prog_set->usage) > 1) {
>> 

Re: [PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy

2018-02-26 Thread Alexei Starovoitov
On Tue, Feb 27, 2018 at 04:40:34AM +, Andy Lutomirski wrote:
> On Tue, Feb 27, 2018 at 2:08 AM, Alexei Starovoitov
>  wrote:
> > On Tue, Feb 27, 2018 at 01:41:15AM +0100, Mickaël Salaün wrote:
> >> The seccomp(2) syscall can be used by a task to apply a Landlock program
> >> to itself. As a seccomp filter, a Landlock program is enforced for the
> >> current task and all its future children. A program is immutable and a
> >> task can only add new restricting programs to itself, forming a list of
> >> programss.
> >>
> >> A Landlock program is tied to a Landlock hook. If the action on a kernel
> >> object is allowed by the other Linux security mechanisms (e.g. DAC,
> >> capabilities, other LSM), then a Landlock hook related to this kind of
> >> object is triggered. The list of programs for this hook is then
> >> evaluated. Each program return a 32-bit value which can deny the action
> >> on a kernel object with a non-zero value. If every programs of the list
> >> return zero, then the action on the object is allowed.
> >>
> >> Multiple Landlock programs can be chained to share a 64-bits value for a
> >> call chain (e.g. evaluating multiple elements of a file path).  This
> >> chaining is restricted when a process construct this chain by loading a
> >> program, but additional checks are performed when it requests to apply
> >> this chain of programs to itself.  The restrictions ensure that it is
> >> not possible to call multiple programs in a way that would imply to
> >> handle multiple shared values (i.e. cookies) for one chain.  For now,
> >> only a fs_pick program can be chained to the same type of program,
> >> because it may make sense if they have different triggers (cf. next
> >> commits).  This restrictions still allows to reuse Landlock programs in
> >> a safe way (e.g. use the same loaded fs_walk program with multiple
> >> chains of fs_pick programs).
> >>
> >> Signed-off-by: Mickaël Salaün 
> >
> > ...
> >
> >> +struct landlock_prog_set *landlock_prepend_prog(
> >> + struct landlock_prog_set *current_prog_set,
> >> + struct bpf_prog *prog)
> >> +{
> >> + struct landlock_prog_set *new_prog_set = current_prog_set;
> >> + unsigned long pages;
> >> + int err;
> >> + size_t i;
> >> + struct landlock_prog_set tmp_prog_set = {};
> >> +
> >> + if (prog->type != BPF_PROG_TYPE_LANDLOCK_HOOK)
> >> + return ERR_PTR(-EINVAL);
> >> +
> >> + /* validate memory size allocation */
> >> + pages = prog->pages;
> >> + if (current_prog_set) {
> >> + size_t i;
> >> +
> >> + for (i = 0; i < ARRAY_SIZE(current_prog_set->programs); i++) 
> >> {
> >> + struct landlock_prog_list *walker_p;
> >> +
> >> + for (walker_p = current_prog_set->programs[i];
> >> + walker_p; walker_p = walker_p->prev)
> >> + pages += walker_p->prog->pages;
> >> + }
> >> + /* count a struct landlock_prog_set if we need to allocate 
> >> one */
> >> + if (refcount_read(_prog_set->usage) != 1)
> >> + pages += round_up(sizeof(*current_prog_set), 
> >> PAGE_SIZE)
> >> + / PAGE_SIZE;
> >> + }
> >> + if (pages > LANDLOCK_PROGRAMS_MAX_PAGES)
> >> + return ERR_PTR(-E2BIG);
> >> +
> >> + /* ensure early that we can allocate enough memory for the new
> >> +  * prog_lists */
> >> + err = store_landlock_prog(_prog_set, current_prog_set, prog);
> >> + if (err)
> >> + return ERR_PTR(err);
> >> +
> >> + /*
> >> +  * Each task_struct points to an array of prog list pointers.  These
> >> +  * tables are duplicated when additions are made (which means each
> >> +  * table needs to be refcounted for the processes using it). When a 
> >> new
> >> +  * table is created, all the refcounters on the prog_list are bumped 
> >> (to
> >> +  * track each table that references the prog). When a new prog is
> >> +  * added, it's just prepended to the list for the new table to point
> >> +  * at.
> >> +  *
> >> +  * Manage all the possible errors before this step to not uselessly
> >> +  * duplicate current_prog_set and avoid a rollback.
> >> +  */
> >> + if (!new_prog_set) {
> >> + /*
> >> +  * If there is no Landlock program set used by the current 
> >> task,
> >> +  * then create a new one.
> >> +  */
> >> + new_prog_set = new_landlock_prog_set();
> >> + if (IS_ERR(new_prog_set))
> >> + goto put_tmp_lists;
> >> + } else if (refcount_read(_prog_set->usage) > 1) {
> >> + /*
> >> +  * If the current task is not the sole user of its Landlock
> >> +  * program set, then duplicate them.
> >> +  */
> >> +  

Re: [PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy

2018-02-26 Thread Andy Lutomirski
On Tue, Feb 27, 2018 at 2:08 AM, Alexei Starovoitov
 wrote:
> On Tue, Feb 27, 2018 at 01:41:15AM +0100, Mickaël Salaün wrote:
>> The seccomp(2) syscall can be used by a task to apply a Landlock program
>> to itself. As a seccomp filter, a Landlock program is enforced for the
>> current task and all its future children. A program is immutable and a
>> task can only add new restricting programs to itself, forming a list of
>> programss.
>>
>> A Landlock program is tied to a Landlock hook. If the action on a kernel
>> object is allowed by the other Linux security mechanisms (e.g. DAC,
>> capabilities, other LSM), then a Landlock hook related to this kind of
>> object is triggered. The list of programs for this hook is then
>> evaluated. Each program return a 32-bit value which can deny the action
>> on a kernel object with a non-zero value. If every programs of the list
>> return zero, then the action on the object is allowed.
>>
>> Multiple Landlock programs can be chained to share a 64-bits value for a
>> call chain (e.g. evaluating multiple elements of a file path).  This
>> chaining is restricted when a process construct this chain by loading a
>> program, but additional checks are performed when it requests to apply
>> this chain of programs to itself.  The restrictions ensure that it is
>> not possible to call multiple programs in a way that would imply to
>> handle multiple shared values (i.e. cookies) for one chain.  For now,
>> only a fs_pick program can be chained to the same type of program,
>> because it may make sense if they have different triggers (cf. next
>> commits).  This restrictions still allows to reuse Landlock programs in
>> a safe way (e.g. use the same loaded fs_walk program with multiple
>> chains of fs_pick programs).
>>
>> Signed-off-by: Mickaël Salaün 
>
> ...
>
>> +struct landlock_prog_set *landlock_prepend_prog(
>> + struct landlock_prog_set *current_prog_set,
>> + struct bpf_prog *prog)
>> +{
>> + struct landlock_prog_set *new_prog_set = current_prog_set;
>> + unsigned long pages;
>> + int err;
>> + size_t i;
>> + struct landlock_prog_set tmp_prog_set = {};
>> +
>> + if (prog->type != BPF_PROG_TYPE_LANDLOCK_HOOK)
>> + return ERR_PTR(-EINVAL);
>> +
>> + /* validate memory size allocation */
>> + pages = prog->pages;
>> + if (current_prog_set) {
>> + size_t i;
>> +
>> + for (i = 0; i < ARRAY_SIZE(current_prog_set->programs); i++) {
>> + struct landlock_prog_list *walker_p;
>> +
>> + for (walker_p = current_prog_set->programs[i];
>> + walker_p; walker_p = walker_p->prev)
>> + pages += walker_p->prog->pages;
>> + }
>> + /* count a struct landlock_prog_set if we need to allocate one 
>> */
>> + if (refcount_read(_prog_set->usage) != 1)
>> + pages += round_up(sizeof(*current_prog_set), PAGE_SIZE)
>> + / PAGE_SIZE;
>> + }
>> + if (pages > LANDLOCK_PROGRAMS_MAX_PAGES)
>> + return ERR_PTR(-E2BIG);
>> +
>> + /* ensure early that we can allocate enough memory for the new
>> +  * prog_lists */
>> + err = store_landlock_prog(_prog_set, current_prog_set, prog);
>> + if (err)
>> + return ERR_PTR(err);
>> +
>> + /*
>> +  * Each task_struct points to an array of prog list pointers.  These
>> +  * tables are duplicated when additions are made (which means each
>> +  * table needs to be refcounted for the processes using it). When a new
>> +  * table is created, all the refcounters on the prog_list are bumped 
>> (to
>> +  * track each table that references the prog). When a new prog is
>> +  * added, it's just prepended to the list for the new table to point
>> +  * at.
>> +  *
>> +  * Manage all the possible errors before this step to not uselessly
>> +  * duplicate current_prog_set and avoid a rollback.
>> +  */
>> + if (!new_prog_set) {
>> + /*
>> +  * If there is no Landlock program set used by the current 
>> task,
>> +  * then create a new one.
>> +  */
>> + new_prog_set = new_landlock_prog_set();
>> + if (IS_ERR(new_prog_set))
>> + goto put_tmp_lists;
>> + } else if (refcount_read(_prog_set->usage) > 1) {
>> + /*
>> +  * If the current task is not the sole user of its Landlock
>> +  * program set, then duplicate them.
>> +  */
>> + new_prog_set = new_landlock_prog_set();
>> + if (IS_ERR(new_prog_set))
>> + goto put_tmp_lists;
>> + for (i = 0; i < ARRAY_SIZE(new_prog_set->programs); i++) {
>> + new_prog_set->programs[i] =
>> +   

Re: [PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy

2018-02-26 Thread Alexei Starovoitov
On Tue, Feb 27, 2018 at 01:41:15AM +0100, Mickaël Salaün wrote:
> The seccomp(2) syscall can be used by a task to apply a Landlock program
> to itself. As a seccomp filter, a Landlock program is enforced for the
> current task and all its future children. A program is immutable and a
> task can only add new restricting programs to itself, forming a list of
> programss.
> 
> A Landlock program is tied to a Landlock hook. If the action on a kernel
> object is allowed by the other Linux security mechanisms (e.g. DAC,
> capabilities, other LSM), then a Landlock hook related to this kind of
> object is triggered. The list of programs for this hook is then
> evaluated. Each program return a 32-bit value which can deny the action
> on a kernel object with a non-zero value. If every programs of the list
> return zero, then the action on the object is allowed.
> 
> Multiple Landlock programs can be chained to share a 64-bits value for a
> call chain (e.g. evaluating multiple elements of a file path).  This
> chaining is restricted when a process construct this chain by loading a
> program, but additional checks are performed when it requests to apply
> this chain of programs to itself.  The restrictions ensure that it is
> not possible to call multiple programs in a way that would imply to
> handle multiple shared values (i.e. cookies) for one chain.  For now,
> only a fs_pick program can be chained to the same type of program,
> because it may make sense if they have different triggers (cf. next
> commits).  This restrictions still allows to reuse Landlock programs in
> a safe way (e.g. use the same loaded fs_walk program with multiple
> chains of fs_pick programs).
> 
> Signed-off-by: Mickaël Salaün 

...

> +struct landlock_prog_set *landlock_prepend_prog(
> + struct landlock_prog_set *current_prog_set,
> + struct bpf_prog *prog)
> +{
> + struct landlock_prog_set *new_prog_set = current_prog_set;
> + unsigned long pages;
> + int err;
> + size_t i;
> + struct landlock_prog_set tmp_prog_set = {};
> +
> + if (prog->type != BPF_PROG_TYPE_LANDLOCK_HOOK)
> + return ERR_PTR(-EINVAL);
> +
> + /* validate memory size allocation */
> + pages = prog->pages;
> + if (current_prog_set) {
> + size_t i;
> +
> + for (i = 0; i < ARRAY_SIZE(current_prog_set->programs); i++) {
> + struct landlock_prog_list *walker_p;
> +
> + for (walker_p = current_prog_set->programs[i];
> + walker_p; walker_p = walker_p->prev)
> + pages += walker_p->prog->pages;
> + }
> + /* count a struct landlock_prog_set if we need to allocate one 
> */
> + if (refcount_read(_prog_set->usage) != 1)
> + pages += round_up(sizeof(*current_prog_set), PAGE_SIZE)
> + / PAGE_SIZE;
> + }
> + if (pages > LANDLOCK_PROGRAMS_MAX_PAGES)
> + return ERR_PTR(-E2BIG);
> +
> + /* ensure early that we can allocate enough memory for the new
> +  * prog_lists */
> + err = store_landlock_prog(_prog_set, current_prog_set, prog);
> + if (err)
> + return ERR_PTR(err);
> +
> + /*
> +  * Each task_struct points to an array of prog list pointers.  These
> +  * tables are duplicated when additions are made (which means each
> +  * table needs to be refcounted for the processes using it). When a new
> +  * table is created, all the refcounters on the prog_list are bumped (to
> +  * track each table that references the prog). When a new prog is
> +  * added, it's just prepended to the list for the new table to point
> +  * at.
> +  *
> +  * Manage all the possible errors before this step to not uselessly
> +  * duplicate current_prog_set and avoid a rollback.
> +  */
> + if (!new_prog_set) {
> + /*
> +  * If there is no Landlock program set used by the current task,
> +  * then create a new one.
> +  */
> + new_prog_set = new_landlock_prog_set();
> + if (IS_ERR(new_prog_set))
> + goto put_tmp_lists;
> + } else if (refcount_read(_prog_set->usage) > 1) {
> + /*
> +  * If the current task is not the sole user of its Landlock
> +  * program set, then duplicate them.
> +  */
> + new_prog_set = new_landlock_prog_set();
> + if (IS_ERR(new_prog_set))
> + goto put_tmp_lists;
> + for (i = 0; i < ARRAY_SIZE(new_prog_set->programs); i++) {
> + new_prog_set->programs[i] =
> + READ_ONCE(current_prog_set->programs[i]);
> + if (new_prog_set->programs[i])
> + refcount_inc(_prog_set->programs[i]->usage);
> + }
> 

[PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy

2018-02-26 Thread Mickaël Salaün
The seccomp(2) syscall can be used by a task to apply a Landlock program
to itself. As a seccomp filter, a Landlock program is enforced for the
current task and all its future children. A program is immutable and a
task can only add new restricting programs to itself, forming a list of
programss.

A Landlock program is tied to a Landlock hook. If the action on a kernel
object is allowed by the other Linux security mechanisms (e.g. DAC,
capabilities, other LSM), then a Landlock hook related to this kind of
object is triggered. The list of programs for this hook is then
evaluated. Each program return a 32-bit value which can deny the action
on a kernel object with a non-zero value. If every programs of the list
return zero, then the action on the object is allowed.

Multiple Landlock programs can be chained to share a 64-bits value for a
call chain (e.g. evaluating multiple elements of a file path).  This
chaining is restricted when a process construct this chain by loading a
program, but additional checks are performed when it requests to apply
this chain of programs to itself.  The restrictions ensure that it is
not possible to call multiple programs in a way that would imply to
handle multiple shared values (i.e. cookies) for one chain.  For now,
only a fs_pick program can be chained to the same type of program,
because it may make sense if they have different triggers (cf. next
commits).  This restrictions still allows to reuse Landlock programs in
a safe way (e.g. use the same loaded fs_walk program with multiple
chains of fs_pick programs).

Signed-off-by: Mickaël Salaün 
Cc: Alexei Starovoitov 
Cc: Andrew Morton 
Cc: Andy Lutomirski 
Cc: James Morris 
Cc: Kees Cook 
Cc: Serge E. Hallyn 
Cc: Will Drewry 
Link: https://lkml.kernel.org/r/c10a503d-5e35-7785-2f3d-25ed8dd63...@digikod.net
---

Changes since v7:
* handle and verify program chains
* split and rename providers.c to enforce.c and enforce_seccomp.c
* rename LANDLOCK_SUBTYPE_* to LANDLOCK_*

Changes since v6:
* rename some functions with more accurate names to reflect that an eBPF
  program for Landlock could be used for something else than a rule
* reword rule "appending" to "prepending" and explain it
* remove the superfluous no_new_privs check, only check global
  CAP_SYS_ADMIN when prepending a Landlock rule (needed for containers)
* create and use {get,put}_seccomp_landlock() (suggested by Kees Cook)
* replace ifdef with static inlined function (suggested by Kees Cook)
* use get_user() (suggested by Kees Cook)
* replace atomic_t with refcount_t (requested by Kees Cook)
* move struct landlock_{rule,events} from landlock.h to common.h
* cleanup headers

Changes since v5:
* remove struct landlock_node and use a similar inheritance mechanisme
  as seccomp-bpf (requested by Andy Lutomirski)
* rename SECCOMP_ADD_LANDLOCK_RULE to SECCOMP_APPEND_LANDLOCK_RULE
* rename file manager.c to providers.c
* add comments
* typo and cosmetic fixes

Changes since v4:
* merge manager and seccomp patches
* return -EFAULT in seccomp(2) when user_bpf_fd is null to easely check
  if Landlock is supported
* only allow a process with the global CAP_SYS_ADMIN to use Landlock
  (will be lifted in the future)
* add an early check to exit as soon as possible if the current process
  does not have Landlock rules

Changes since v3:
* remove the hard link with seccomp (suggested by Andy Lutomirski and
  Kees Cook):
  * remove the cookie which could imply multiple evaluation of Landlock
rules
  * remove the origin field in struct landlock_data
* remove documentation fix (merged upstream)
* rename the new seccomp command to SECCOMP_ADD_LANDLOCK_RULE
* internal renaming
* split commit
* new design to be able to inherit on the fly the parent rules

Changes since v2:
* Landlock programs can now be run without seccomp filter but for any
  syscall (from the process) or interruption
* move Landlock related functions and structs into security/landlock/*
  (to manage cgroups as well)
* fix seccomp filter handling: run Landlock programs for each of their
  legitimate seccomp filter
* properly clean up all seccomp results
* cosmetic changes to ease the understanding
* fix some ifdef
---
 include/linux/landlock.h|  37 
 include/linux/seccomp.h |   5 +
 include/uapi/linux/seccomp.h|   1 +
 kernel/fork.c   |   8 +-
 kernel/seccomp.c|   4 +
 security/landlock/Makefile  |   3 +-
 security/landlock/chain.c   |  39 
 security/landlock/chain.h   |  35 
 security/landlock/common.h  |  53 +
 security/landlock/enforce.c | 386 
 security/landlock/enforce.h |  21 ++
 security/landlock/enforce_seccomp.c | 102 ++
 12 files changed, 692 insertions(+), 2