Linux CIFS filesystem development
 help / color / mirror / Atom feed
From: Jeff Layton <jlayton@samba.org>
To: Shirish Pargaonkar <shirishpargaonkar@gmail.com>, smfrench@gmail.com
Cc: dhowells@redhat.com, linux-cifs@vger.kernel.org,
	samba-technical <samba-technical@lists.samba.org>
Subject: Re: [PATCH] cifs: Support for an upcall to map SID to an uid and a gid
Date: Sat, 11 Dec 2010 19:30:03 -0500	[thread overview]
Message-ID: <20101211193003.4a11fc7f@corrin.poochiereds.net> (raw)
In-Reply-To: <AANLkTimiD_iAJveTFpsANQsJC_cUfRwHM=jO5FSoj4x_@mail.gmail.com>

On Sat, 11 Dec 2010 15:47:12 -0600
Shirish Pargaonkar <shirishpargaonkar@gmail.com> wrote:

> On Sat, Dec 11, 2010 at 10:17 AM, Jeff Layton <jlayton@samba.org> wrote:
> > On Tue,  7 Dec 2010 11:11:12 -0600
> > shirishpargaonkar@gmail.com wrote:
> >
> >> From: Shirish Pargaonkar <shirishpargaonkar@gmail.com>
> >>
> >>
> >> Use a cifs upcall to map a SID to either an uid or a gid using
> >> winbind.
> >>
> >> There is a corrosponding patch for the cifs.upcall binary in cifs-utils rpm
> >> that is being posted also.
> >>
> >> A new type of key, cifs_acl_key_type, is used.
> >> To map a SID, which can be either a Onwer SID or a Group SID, key
> >> description starts with the string "os" or "gs" followed by SID converted
> >> to a string. Without "os" or "gs", cifs.upcall does not know whether
> >> SID needs to be mapped to either an uid or a gid.
> >>
> >> Once a key is instantiated, get rid of it since cifs does not need to
> >> use in any way.
> >> winbind does the id mapping and looks up name for the newly mapped
> >> SID/uid or SID/gid combination.
> >>
> >> For now, cifs.upcall is only used to map a SID to an id (uid or gid) but
> >> it would be used to obtain an SID (string) for an id.
> >>
> >> An entry such as this
> >>
> >> create  cifs.cifs_acl   *       *               /usr/sbin/cifs.upcall %k
> >>
> >> is needed in the file /etc/request-key.conf.
> >>
> >>
> >> Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com>
> >> ---
> >>  fs/cifs/cifsacl.c |  117 ++++++++++++++++++++++++++++++++++++++++++++++++-----
> >>  fs/cifs/cifsacl.h |    8 ++++
> >>  fs/cifs/cifsfs.c  |    7 +++
> >>  3 files changed, 122 insertions(+), 10 deletions(-)
> >>
> >> diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
> >> index a520091..d3ac6c8 100644
> >> --- a/fs/cifs/cifsacl.c
> >> +++ b/fs/cifs/cifsacl.c
> >> @@ -23,6 +23,9 @@
> >>
> >>  #include <linux/fs.h>
> >>  #include <linux/slab.h>
> >> +#include <linux/string.h>
> >> +#include <keys/user-type.h>
> >> +#include <linux/key-type.h>
> >>  #include "cifspdu.h"
> >>  #include "cifsglob.h"
> >>  #include "cifsacl.h"
> >> @@ -52,6 +55,102 @@ static const struct cifs_sid sid_authusers = {
> >>  /* group users */
> >>  static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
> >>
> >> +static int
> >> +cifs_acl_key_instantiate(struct key *key, const void *data, size_t datalen)
> >> +{
> >> +     char *payload;
> >> +
> >> +     payload = kmalloc(datalen, GFP_KERNEL);
> >> +     if (!payload)
> >> +             return -ENOMEM;
> >> +
> >> +     memcpy(payload, data, datalen);
> >> +     key->payload.data = payload;
> >> +     return 0;
> >> +}
> >> +
> >> +static void
> >> +cifs_acl_key_destroy(struct key *key)
> >> +{
> >> +     kfree(key->payload.data);
> >> +}
> >> +
> >> +struct key_type cifs_acl_key_type = {
> >> +     .name        = "cifs.cifs_acl",
> >> +     .instantiate = cifs_acl_key_instantiate,
> >> +     .destroy     = cifs_acl_key_destroy,
> >> +     .describe    = user_describe,
> >> +     .match       = user_match,
> >> +};
> >> +
> >
> > Nit: these don't have so much to do with ACL's per-se, as much as
> > idmapping. Maybe these functions and the key type should be called
> > "cifs_idmap_*" and "cifs.idmap" ? It might be clearer to admins what
> > this is for.
> 
> Yes, will change the name as you suggested, that sounds right, rather
> that acl.
> 
> >
> >> +static void
> >> +sid_to_str(struct cifs_sid *sidptr, char *sidstr)
> >> +{
> >> +     int i;
> >> +     unsigned long saval;
> >> +     char *strptr;
> >> +
> >> +     strptr = sidstr;
> >> +
> >> +     sprintf(strptr, "%s", "S");
> >> +     strptr = sidstr + strlen(sidstr);
> >> +
> >> +     sprintf(strptr, "-%d", sidptr->revision);
> >> +     strptr = sidstr + strlen(sidstr);
> >> +
> >> +     for (i = 0; i < 6; ++i) {
> >> +             if (sidptr->authority[i]) {
> >> +                     sprintf(strptr, "-%d", sidptr->authority[i]);
> >> +                     strptr = sidstr + strlen(sidstr);
> >> +             }
> >> +     }
> >> +
> >> +     for (i = 0; i < sidptr->num_subauth; ++i) {
> >> +             saval = le32_to_cpu(sidptr->sub_auth[i]);
> >> +             sprintf(strptr, "-%ld", saval);
> >> +             strptr = sidstr + strlen(sidstr);
> >> +     }
> >> +}
> >> +
> >> +static int
> >> +sid_to_id(struct cifs_sid *psid, struct cifs_fattr *fattr, uint sidtype)
> >> +{
> >> +     int rc = 0;
> >> +     char *sidstr, *strptr;
> >> +     struct key *idkey;
> >> +
> >> +     sidstr = kzalloc(SIDLEN, GFP_KERNEL);
> >> +     if (!sidstr)
> >> +             return -ENOMEM;
> >> +     strptr = sidstr;
> >> +
> >> +     if (sidtype == SIDOWNER)
> >> +             sprintf(strptr, "%s", "os:");
> >> +     else if (sidtype == SIDGROUP)
> >> +             sprintf(strptr, "%s", "gs:");
> >> +     else {
> >> +             rc = -EINVAL;
> >> +             goto idresolve_err;
> >> +     }
> >> +     strptr = sidstr + strlen(sidstr);
> >> +
> >> +     sid_to_str(psid, strptr);
> >> +
> >> +     idkey = request_key(&cifs_acl_key_type, sidstr, "");
> >> +     if (IS_ERR(idkey))
> >> +             cFYI(1, "%s: idkey error: %d\n", __func__, -ENOKEY);
> >> +     else {
> >> +             if (sidtype == SIDOWNER)
> >> +                     fattr->cf_uid = *(unsigned long *)idkey->payload.value;
> >> +             else if (sidtype == SIDGROUP)
> >> +                     fattr->cf_gid = *(unsigned long *)idkey->payload.value;
> >> +             key_put(idkey);
> >> +     }
> >> +
> >> +idresolve_err:
> >> +     kfree(sidstr);
> >> +     return rc;
> >> +}
> >>
> >
> > What about security? With this code, it'll be possible for a user to
> > "stuff" the cache with idmapping. In the situation where the kernel is
> > trying to enforce permissions on the client, it'll be possible to
> > trick it into mapping a sid to a uid of your choosing. I think you need
> > to guard against that.
> 
> That means cifs module will have to know what was the range of ids for
> uids and gids to be allocated by winbind as dictated by entries in
> smb.conf and if a returned id happens not to be in that range, discard it
> and assign default id of 0 (root).
> winbind know the range from smb.conf, it could be any smb.conf file,
> not necessarily under /etc/samba/smb.conf.
> How would cifs module know that range.
> Not sure if winbind has an API to query the ranges.  And even if it had,
> it is possible that winbind deamon itself is not running.
> 

Maybe I wasn't clear... The danger here is that I have the ability to
put info of my own choosing into my keyring via an add_key() syscall
from userspace.

You need to do something like the override_creds trick that dns_query
does.

> >
> > You'll also be doing an upcall every time a different user needs to map
> > a SID to a UID/GID.
> >
> > Finally, calling into the keys API every time you want to map an ID
> > sounds rather inefficient. This might take quite some time if you were
> > doing "ls -l" on a large directory.
> >
> > Would it be better to consider taking the info in the key and
> > populating a different cache? You could register it with a shrinker and
> > prune off LRU entries if memory gets tight.
> >
> 
> Will look into this.  One thing that concerns me is if a cached etnry
> for a SID with its name and an id (either an uid or a gid), if that SID
> now represents a different object and has differernt name, would
> not cached info be incorrect?  Not sure if this can ever happen
> or how would it happen and if it does, what would be a trigger
> for a cache revalidation and purges!
> 

Sure, mappings can change. But, you still have the same problem with
what you're proposing in these patches. The userspace program isn't
setting a timeout on the key. Once a mapping is put in the keyring,
it's there until it's revoked. You probably want to set a max TTL for
the entries in the cache regardless of what scheme is used.

idmap lookups need to be pretty fast as you'll be calling them a lot.
Consider the case of "ls -l" on a large directory. Some slowness for
the upcall to populate the entry in the cache is probably acceptable.
Slowness on subsequent cached lookups of that same entry will be
painful.

-- 
Jeff Layton <jlayton@samba.org>

  reply	other threads:[~2010-12-12  0:30 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-12-07 17:11 [PATCH] cifs: Support for an upcall to map SID to an uid and a gid shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w
     [not found] ` <20101211111716.1e21be41@corrin.poochiereds.net>
     [not found]   ` <20101211111716.1e21be41-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
2010-12-11 21:47     ` Shirish Pargaonkar
2010-12-12  0:30       ` Jeff Layton [this message]
2010-12-12  0:57         ` Richard Sharpe
     [not found]           ` <AANLkTiniGp28dxZuoTcjyp0OMEoQ-7E0yE6T8B+VHOLj-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-12-12  3:11             ` Jeff Layton
     [not found]               ` <20101211221159.36e6c814-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
2010-12-12  3:48                 ` Andrew Bartlett
2010-12-12 11:39                   ` Jeff Layton
     [not found]                     ` <20101212063929.77a619e4-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org>
2010-12-13  3:22                       ` Andrew Bartlett
2010-12-13 11:16                         ` Jeff Layton
2010-12-14 22:29                           ` Shirish Pargaonkar
     [not found]                           ` <20101213061622.7e78e475-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org>
2010-12-14 22:42                             ` Andrew Bartlett

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=20101211193003.4a11fc7f@corrin.poochiereds.net \
    --to=jlayton@samba.org \
    --cc=dhowells@redhat.com \
    --cc=linux-cifs@vger.kernel.org \
    --cc=samba-technical@lists.samba.org \
    --cc=shirishpargaonkar@gmail.com \
    --cc=smfrench@gmail.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