Whamcloud - gitweb
LU-14739 quota: nodemap squashed root cannot bypass quota
[fs/lustre-release.git] / lustre / mdt / mdt_identity.c
index e8ec709..8729299 100644 (file)
@@ -27,7 +27,6 @@
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
  *
  * lustre/mdt/mdt_identity.c
  *
 
 #define DEBUG_SUBSYSTEM S_MDS
 
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/kmod.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/version.h>
-#include <linux/unistd.h>
-#include <asm/uaccess.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <asm/uaccess.h>
-#include <linux/slab.h>
-
-#include <libcfs/libcfs.h>
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_dlm.h>
-#include <lustre_lib.h>
-
 #include "mdt_internal.h"
 
 static void mdt_identity_entry_init(struct upcall_cache_entry *entry,
-                                    void *unused)
+                                   void *unused)
 {
-        entry->u.identity.mi_uc_entry = entry;
+       entry->u.identity.mi_uc_entry = entry;
 }
 
 static void mdt_identity_entry_free(struct upcall_cache *cache,
@@ -81,41 +56,49 @@ static void mdt_identity_entry_free(struct upcall_cache *cache,
 
        if (identity->mi_nperms) {
                LASSERT(identity->mi_perms);
-               OBD_FREE(identity->mi_perms,
-                        identity->mi_nperms * sizeof(struct md_perm));
+               OBD_FREE_PTR_ARRAY(identity->mi_perms, identity->mi_nperms);
                identity->mi_nperms = 0;
        }
 }
 
 static int mdt_identity_do_upcall(struct upcall_cache *cache,
-                                  struct upcall_cache_entry *entry)
+                                 struct upcall_cache_entry *entry)
 {
-        char keystr[16];
-        char *argv[] = {
-                  [0] = cache->uc_upcall,
-                  [1] = cache->uc_name,
-                  [2] = keystr,
-                  [3] = NULL
-        };
-        char *envp[] = {
-                  [0] = "HOME=/",
-                  [1] = "PATH=/sbin:/usr/sbin",
-                  [2] = NULL
-        };
+       char keystr[16];
+       char *argv[] = {
+               [0] = cache->uc_upcall,
+               [1] = cache->uc_name,
+               [2] = keystr,
+               [3] = NULL
+       };
+       char *envp[] = {
+               [0] = "HOME=/",
+               [1] = "PATH=/sbin:/usr/sbin",
+               [2] = NULL
+       };
        ktime_t start, end;
-        int rc;
-        ENTRY;
+       int rc;
 
-        /* There is race condition:
-         * "uc_upcall" was changed just after "is_identity_get_disabled" check.
-         */
+       ENTRY;
+       /* There is race condition:
+        * "uc_upcall" was changed just after "is_identity_get_disabled" check.
+        */
        down_read(&cache->uc_upcall_rwsem);
-        CDEBUG(D_INFO, "The upcall is: '%s'\n", cache->uc_upcall);
+       CDEBUG(D_INFO, "The upcall is: '%s'\n", cache->uc_upcall);
 
-        if (unlikely(!strcmp(cache->uc_upcall, "NONE"))) {
-                CERROR("no upcall set\n");
-                GOTO(out, rc = -EREMCHG);
-        }
+       if (unlikely(!strcmp(cache->uc_upcall, "NONE"))) {
+               rc = -EREMCHG;
+               CERROR("%s: extended identity requested for user '%llu' called with 'NONE' upcall: rc = %d\n",
+                      cache->uc_name, entry->ue_key, rc);
+               GOTO(out, rc);
+       }
+
+       if (unlikely(cache->uc_upcall[0] == '\0')) {
+               rc = -EREMCHG;
+               CERROR("%s: extended identity requested for user '%llu' called with empty upcall: rc = %d\n",
+                      cache->uc_name, entry->ue_key, rc);
+               GOTO(out, rc);
+       }
 
        argv[0] = cache->uc_upcall;
        snprintf(keystr, sizeof(keystr), "%llu", entry->ue_key);
@@ -124,9 +107,9 @@ static int mdt_identity_do_upcall(struct upcall_cache *cache,
        rc = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
        end = ktime_get();
        if (rc < 0) {
-               CERROR("%s: error invoking upcall %s %s %s: rc %d; check /proc/fs/lustre/mdt/%s/identity_upcall, time %ldus\n",
+               CERROR("%s: error invoking upcall %s %s %s: rc %d; check /proc/fs/lustre/mdt/%s/identity_upcall, time %ldus: rc = %d\n",
                       cache->uc_name, argv[0], argv[1], argv[2], rc,
-                      cache->uc_name, (long)ktime_us_delta(end, start));
+                      cache->uc_name, (long)ktime_us_delta(end, start), rc);
        } else {
                CDEBUG(D_HA, "%s: invoked upcall %s %s %s, time %ldus\n",
                       cache->uc_name, argv[0], argv[1], argv[2],
@@ -147,18 +130,24 @@ static int mdt_identity_parse_downcall(struct upcall_cache *cache,
        struct identity_downcall_data *data = args;
        struct group_info *ginfo = NULL;
        struct md_perm *perms = NULL;
-       int size, i;
-       ENTRY;
+       int size, i, rc = 0;
 
+       ENTRY;
        LASSERT(data);
-       if (data->idd_ngroups > NGROUPS_MAX)
-               RETURN(-E2BIG);
+       if (data->idd_ngroups > NGROUPS_MAX) {
+               rc = -E2BIG;
+               CERROR("%s: UID %u groups %u > maximum %u: rc = %d\n",
+                      cache->uc_name, data->idd_uid, data->idd_ngroups, NGROUPS_MAX, rc);
+               goto out;
+       }
 
        if (data->idd_ngroups > 0) {
                ginfo = groups_alloc(data->idd_ngroups);
                if (!ginfo) {
-                       CERROR("failed to alloc %d groups\n", data->idd_ngroups);
-                       RETURN(-ENOMEM);
+                       rc = -ENOMEM;
+                       CERROR("%s: failed to alloc %d groups: rc = %d\n",
+                              cache->uc_name, data->idd_ngroups, rc);
+                       goto out;
                }
 
                lustre_groups_from_list(ginfo, data->idd_groups);
@@ -169,11 +158,12 @@ static int mdt_identity_parse_downcall(struct upcall_cache *cache,
                size = data->idd_nperms * sizeof(*perms);
                OBD_ALLOC(perms, size);
                if (!perms) {
-                       CERROR("failed to alloc %d permissions\n",
-                              data->idd_nperms);
-                       if (ginfo != NULL)
+                       rc = -ENOMEM;
+                       CERROR("%s: failed to alloc %d permissions: rc = %d\n",
+                              cache->uc_name, data->idd_nperms, rc);
+                       if (ginfo)
                                put_group_info(ginfo);
-                       RETURN(-ENOMEM);
+                       goto out;
                }
 
                for (i = 0; i < data->idd_nperms; i++) {
@@ -192,47 +182,48 @@ static int mdt_identity_parse_downcall(struct upcall_cache *cache,
               identity, identity->mi_uid, identity->mi_gid,
               data->idd_ngroups, data->idd_nperms);
 
-       RETURN(0);
+out:
+       RETURN(rc);
 }
 
 struct md_identity *mdt_identity_get(struct upcall_cache *cache, __u32 uid)
 {
-        struct upcall_cache_entry *entry;
-
-        if (!cache)
-                return ERR_PTR(-ENOENT);
-
-        entry = upcall_cache_get_entry(cache, (__u64)uid, NULL);
-        if (IS_ERR(entry))
-                return ERR_PTR(PTR_ERR(entry));
-        else if (unlikely(!entry))
-                return ERR_PTR(-ENOENT);
-        else
-                return &entry->u.identity;
+       struct upcall_cache_entry *entry;
+
+       if (!cache)
+               return ERR_PTR(-ENOENT);
+
+       entry = upcall_cache_get_entry(cache, (__u64)uid, NULL);
+       if (unlikely(!entry))
+               return ERR_PTR(-ENOENT);
+       if (IS_ERR(entry))
+               return ERR_CAST(entry);
+
+       return &entry->u.identity;
 }
 
 void mdt_identity_put(struct upcall_cache *cache, struct md_identity *identity)
 {
-        if (!cache)
-                return;
+       if (!cache)
+               return;
 
-        LASSERT(identity);
-        upcall_cache_put_entry(cache, identity->mi_uc_entry);
+       LASSERT(identity);
+       upcall_cache_put_entry(cache, identity->mi_uc_entry);
 }
 
 struct upcall_cache_ops mdt_identity_upcall_cache_ops = {
-        .init_entry     = mdt_identity_entry_init,
-        .free_entry     = mdt_identity_entry_free,
-        .do_upcall      = mdt_identity_do_upcall,
-        .parse_downcall = mdt_identity_parse_downcall,
+       .init_entry     = mdt_identity_entry_init,
+       .free_entry     = mdt_identity_entry_free,
+       .do_upcall      = mdt_identity_do_upcall,
+       .parse_downcall = mdt_identity_parse_downcall,
 };
 
 void mdt_flush_identity(struct upcall_cache *cache, int uid)
 {
-        if (uid < 0)
-                upcall_cache_flush_idle(cache);
-        else
-                upcall_cache_flush_one(cache, (__u64)uid, NULL);
+       if (uid < 0)
+               upcall_cache_flush_idle(cache);
+       else
+               upcall_cache_flush_one(cache, (__u64)uid, NULL);
 }
 
 /*
@@ -241,26 +232,25 @@ void mdt_flush_identity(struct upcall_cache *cache, int uid)
  */
 __u32 mdt_identity_get_perm(struct md_identity *identity, lnet_nid_t nid)
 {
-
        struct md_perm *perm;
        int i;
 
        if (!identity)
                return CFS_SETGRP_PERM;
 
-        perm = identity->mi_perms;
-        /* check exactly matched nid first */
-        for (i = identity->mi_nperms - 1; i > 0; i--) {
-                if (perm[i].mp_nid != nid)
-                        continue;
-                return perm[i].mp_perm;
-        }
+       perm = identity->mi_perms;
+       /* check exactly matched nid first */
+       for (i = identity->mi_nperms - 1; i > 0; i--) {
+               if (perm[i].mp_nid != nid)
+                       continue;
+               return perm[i].mp_perm;
+       }
 
-        /* check LNET_NID_ANY then */
-        if ((identity->mi_nperms > 0) &&
-            ((perm[0].mp_nid == nid) || (perm[0].mp_nid == LNET_NID_ANY)))
-                return perm[0].mp_perm;
+       /* check LNET_NID_ANY then */
+       if ((identity->mi_nperms > 0) &&
+           ((perm[0].mp_nid == nid) || (perm[0].mp_nid == LNET_NID_ANY)))
+               return perm[0].mp_perm;
 
-        /* return default last */
+       /* return default last */
        return CFS_SETGRP_PERM;
 }