outreachy.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
From: "Mickaël Salaün" <mic@digikod.net>
To: Tahera Fahimi <fahimitahera@gmail.com>
Cc: Paul Moore <paul@paul-moore.com>, outreachy@lists.linux.dev
Subject: Re: [PATCH] Adding helpers for unix_stream_connect.
Date: Thu, 28 Mar 2024 15:42:24 +0100	[thread overview]
Message-ID: <20240328.ShoR4Iecei8o@digikod.net> (raw)
In-Reply-To: <ZgToAL0HpTvr3l6G@tahera-OptiPlex-5000>

On Wed, Mar 27, 2024 at 09:46:08PM -0600, Tahera Fahimi wrote:
> On Tue, Mar 26, 2024 at 12:28:36PM +0100, Mickaël Salaün wrote:
> > CCing Outreachy mailing list and Paul.
> > 
> > Related GitHub issue: https://github.com/landlock-lsm/linux/issues/7
> > 
> > On Sun, Mar 24, 2024 at 10:24:53PM -0600, TaheraFahimi wrote:
> > > Signed-off-by: TaheraFahimi <fahimitahera@gmail.com>
> > 
> > I guess there is a space missing between your first and last name.
> > 
> > > ---
> > >  security/landlock/task.c | 89 ++++++++++++++++++++++++++++++++++++++++
> > >  1 file changed, 89 insertions(+)
> > > 
> > > diff --git a/security/landlock/task.c b/security/landlock/task.c
> > > index 849f5123610b..10195492c169 100644
> > > --- a/security/landlock/task.c
> > > +++ b/security/landlock/task.c
> > > @@ -14,6 +14,10 @@
> > >  #include <linux/rcupdate.h>
> > >  #include <linux/sched.h>
> > >  
> > > +/*to use sock structure*/
> > > +#include <net/sock.h>
> > > +#include <linux/spinlock.h>
> > > +
> > >  #include "common.h"
> > >  #include "cred.h"
> > >  #include "ruleset.h"
> > > @@ -108,9 +112,94 @@ static int hook_ptrace_traceme(struct task_struct *const parent)
> > >  	return task_ptrace(parent, current);
> > >  }
> > >  
> > > +
> > > +/** 
> > > + * sk_get_peer_cred : Helper Function from socket.c
> > > + * This helper is used to retrieve the sk_peer credentioals.
> > > + */
> > > +static const struct cred *sk_get_peer_cred(struct sock *sk)
> > > +{
> > > +        const struct cred *cred;
> > > +        spin_lock(&sk->sk_peer_lock);
> > > +        cred = get_cred(sk->sk_peer_cred);
> > > +        spin_unlock(&sk->sk_peer_lock);
> > > +        return cred;
> > > +}
> > > +/**
> > > + * Use domain_scope_le() to scope the access same as ptrace trask.
> > > + */
> > > +static bool unix_sock_is_scoped(struct sock *const sock,
> > > +                                struct sock *const other)
> > > +{
> > > +
> > > +        bool is_scoped = true;
> > > +        /* retrieve the credential of socks.
> > > +	 * other->sk_peer_cred shows the listening socket credentials (This credential
> > > +	 *  is created at the init_cred function and will be coped to 
> > > +	 *  sock->sk_peer_cred later.) 
> > > +	 * Since sock is the connecting sock, then the credential of current task is equal
> > > +	 * to cred_sock.
> > > +	 *  */
> > > +        const struct cred *cred_other;
> > > +	cred_other = sk_get_peer_cred(other);
> > > +	
> > > +	
> > > +	const struct cred *cred_sock;
> > > +	spin_lock(&sock->sk_peer_lock);
> > 
> > You don't need a lock for get_current_cred(), and sk_peer_lock is
> > unrelated to current.  Moreover, security_unix_stream_connect() is
> > already called while the lock being held.
> > 
> > > +	cred_sock = get_current_cred();
> > > +	spin_unlock(&sock->sk_peer_lock);
> > 
> > You should just use landlock_get_current_domain().
> > 
> > > +
> > > +	printk(KERN_DEBUG "cred uid: %u\n", cred_other->gid);
> > 
> > You can use pr_warn() instead.
> > 
> > > +	//printk("the cred_sock kuid is : %llx\n", cred_sock->uid);
> > > +        /* retrieve the landlock_rulesets*/
> > > +	
> > > +	printk("The credentials is retrieved!!\n");
> > > +        
> > > +	const struct landlock_cred_security *dom_parent, *dom_child;
> > 
> > dom_* variables should only be used to refer do a Landlock domain, not
> > credential.
> > 
> > > +        const struct landlock_ruleset *parent, *child;
> > > +        rcu_read_lock();
> > > +        dom_parent = landlock_cred(cred_other);
> > > +	dom_child = landlock_cred(cred_sock);
> > > +        parent = dom_parent->domain;
> > > +        child = dom_child->domain;
> > > +	/* by uncommenting either the following if statement or calling 
> > > +	 * the domain_scope_le the kernel will not load(make task dead)*/
> > > +	//if (dom_parent)
> > > +	//	printk("parent num rules %u\n", parent->num_rules);
> > > +	if (child)
> > > +		printk("child num rules %u\n", child->num_rules);
> > > +	//is_scoped = domain_scope_le(parent, child);
> > > +        rcu_read_unlock();
> > > +	
> > > +
> > > +        return is_scoped;
> > > +}
> > > +/**
> > > + * unix_stream_connect -
> > > + */
> > > +static int task_unix_stream_connect(struct sock *const sock,
> > > +                               struct sock *const other,
> > > +                               struct sock *const newsk)
> > > +{
> > > +        /* How do we check if the scoping is optional?  */
> > > +        if (unix_sock_is_scoped(sock, other))
> > > +                return 0;
> > > +        return -EPERM;
> > > +}
> > > +
> > > +/**
> > > + * hook_unix_stream_connect -
> > > + */
> > > +static int hook_unix_stream_connect(struct sock *const sock, struct sock *const other,
> > > +                                    struct sock *const newsk)
> > > +{
> > > +        return task_unix_stream_connect(sock, other, newsk);
> > > +}
> > > +
> > >  static struct security_hook_list landlock_hooks[] __ro_after_init = {
> > >  	LSM_HOOK_INIT(ptrace_access_check, hook_ptrace_access_check),
> > >  	LSM_HOOK_INIT(ptrace_traceme, hook_ptrace_traceme),
> > > +        LSM_HOOK_INIT(unix_stream_connect, hook_unix_stream_connect),
> > >  };
> > >  
> > >  __init void landlock_add_task_hooks(void)
> > > -- 
> > > 2.34.1
> > > 
> > > Hello Mickaël, I made the following changes to have an lsm hook function for "unix_stream_connect". I have an issue, and I was wondering  if you could give me a hint. At first, I retrieve the Socks' credentials through "sk_get_peer_cred" and "get_current_cred". As "get_current_cred" gives us the credential related to the sock and "sk_get_peer_cred" gives the sock's peer credential(this credential will be copied to the field sock->sk_peer_cred later). Then I uses both credentials to get their "landlock_cred_security". Since "landlock_cred_security" has a pointer to the "landlock_ruleset", we can pass their rulesets to the "domain_scope_le" (same as ptrace task) to check if it is scoped or not.
> > 
> > Hello Tahera, this approach looks good.  However, Landlock credential's
> > domain may be NULL (when the task is not sandboxed).
> > 
> > > The problem is that If I uncomment the "domain_scope_le", the kernel will not work. I think it can not get the "landlock_cred_security". Thank you :)
> > 
> > "the kernel will not work" could means a lot of things. We need a more
> > precise description.
> > 
> > I guess this is just a draft and the patch is not ready yet so it's
> > fine. Before sending a first official version you should follow and read
> > the referenced links and especially the kernel patch how-to here:
> > https://lore.kernel.org/outreachy/ZeZzLWtk2nZ1Pcgw@aschofie-mobl2/
> > For instance, you should run checkpatch.pl
> > For Landlock-specific patches, they need to be formatted with
> > clang-format (-i) and pass all the checked done by check-linux.sh
> > provided here: https://github.com/landlock-lsm/landlock-test-tools
> Hello Mickaël,
> Thanks for the hints. As you mentioned, it was just a draft. Besides the check-linux.sh checks, is there any other checks that I can test my code with them? Or should I sandbox a task and test the codes with that?

Please send a complete patch taking into account my review (and with a
link to this initial draft).

Then, you can write new tests using the hierarchy variants from
tools/testing/selftests/landlock/ptrace_test.c (I'll probably rename the
file but you don't need to worry about that).  The new TEST_F(hierarchy,
abstract_unix_socket) should be pretty similar to TEST_F(hierarchy,
trace) but without the ptrace and Yama specificities.

When your tests will be OK, you can send a new patch series (new
version) with one patch for the kernel changes and another for the new
tests.  You'll also need to write the user documentation in another
patch.

> Thanks again,
> Also, In my previous I forgot to copy outreachy email, so I sent this email again.
> Regards,
> Tahera
> 

  reply	other threads:[~2024-03-28 14:42 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <ZgD8lTToWEhtNmpg@tahera-OptiPlex-5000>
2024-03-26 11:28 ` [PATCH] Adding helpers for unix_stream_connect Mickaël Salaün
2024-03-28  3:46   ` Tahera Fahimi
2024-03-28 14:42     ` Mickaël Salaün [this message]
2024-03-30  3:43       ` Tahera Fahimi
2024-04-02 14:35         ` Mickaël Salaün

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240328.ShoR4Iecei8o@digikod.net \
    --to=mic@digikod.net \
    --cc=fahimitahera@gmail.com \
    --cc=outreachy@lists.linux.dev \
    --cc=paul@paul-moore.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).