/*
* fs/cifs/cifsacl.c
*
* Copyright (C) International Business Machines Corp., 2007,2008
* Author(s): Steve French (sfrench@us.ibm.com)
*
* Contains the routines for mapping CIFS/NTFS ACLs
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/keyctl.h>
#include <linux/key-type.h>
#include <keys/user-type.h>
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsacl.h"
#include "cifsproto.h"
#include "cifs_debug.h"
/* security id for everyone/world system group */
static const struct cifs_sid sid_everyone = {
1, 1, {0, 0, 0, 0, 0, 1}, {0} };
/* security id for Authenticated Users system group */
static const struct cifs_sid sid_authusers = {
1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11)} };
/* group users */
static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
const struct cred *root_cred;
static void
shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem,
int *nr_del)
{
struct rb_node *node;
struct rb_node *tmp;
struct cifs_sid_id *psidid;
node = rb_first(root);
while (node) {
tmp = node;
node = rb_next(tmp);
psidid = rb_entry(tmp, struct cifs_sid_id, rbnode);
if (nr_to_scan == 0 || *nr_del == nr_to_scan)
++(*nr_rem);
else {
if (time_after(jiffies, psidid->time + SID_MAP_EXPIRE)
&& psidid->refcount == 0) {
rb_erase(tmp, root);
++(*nr_del);
} else
++(*nr_rem);
}
}
}
/*
* Run idmap cache shrinker.
*/
static int
cifs_idmap_shrinker(struct shrinker *shrink, struct shrink_control *sc)
{
int nr_to_scan = sc->nr_to_scan;
int nr_del = 0;
int nr_rem = 0;
struct rb_root *root;
root = &uidtree;
spin_lock(&siduidlock);
shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
spin_unlock(&siduidlock);
root = &gidtree;
spin_lock(&sidgidlock);
shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
spin_unlock(&sidgidlock);
return nr_rem;
}
static struct shrinker cifs_shrinker = {
.shrink = cifs_idmap_shrinker,
.seeks = DEFAULT_SEEKS,
};
static int
cifs_idmap_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;