Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / mdt / mdt_lib.c
index 410ad51..b3dc462 100644 (file)
@@ -1,36 +1,49 @@
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
- *  lustre/mdt/mdt_lib.c
- *  Lustre Metadata Target (mdt) request unpacking helper.
+ * GPL HEADER START
  *
- *  Copyright (c) 2006 Cluster File Systems, Inc.
- *   Author: Peter Braam <braam@clusterfs.com>
- *   Author: Andreas Dilger <adilger@clusterfs.com>
- *   Author: Phil Schwan <phil@clusterfs.com>
- *   Author: Mike Shaver <shaver@clusterfs.com>
- *   Author: Nikita Danilov <nikita@clusterfs.com>
- *   Author: Huang Hua <huanghua@clusterfs.com>
- *   Author: Fan Yong <fanyong@clusterfs.com>
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
  *
- *   This file is part of the Lustre file system, http://www.lustre.org
- *   Lustre is a trademark of Cluster File Systems, Inc.
+ * This program 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
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
  *
- *   You may have signed or agreed to another license before downloading
- *   this software.  If so, you are bound by the terms and conditions
- *   of that agreement, and the following does not apply to you.  See the
- *   LICENSE file included with this distribution for more information.
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
  *
- *   If you did not agree to a different license, then this copy of Lustre
- *   is open source software; you can redistribute it and/or modify it
- *   under the terms of version 2 of the GNU General Public License as
- *   published by the Free Software Foundation.
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
  *
- *   In either case, Lustre 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
- *   license text for more details.
+ * GPL HEADER END
+ */
+/*
+ * Copyright  2008 Sun Microsystems, Inc. All rights reserved
+ * Use is subject to license terms.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
+ *
+ * lustre/mdt/mdt_lib.c
+ *
+ * Lustre Metadata Target (mdt) request unpacking helper.
+ *
+ * Author: Peter Braam <braam@clusterfs.com>
+ * Author: Andreas Dilger <adilger@clusterfs.com>
+ * Author: Phil Schwan <phil@clusterfs.com>
+ * Author: Mike Shaver <shaver@clusterfs.com>
+ * Author: Nikita Danilov <nikita@clusterfs.com>
+ * Author: Huang Hua <huanghua@clusterfs.com>
+ * Author: Fan Yong <fanyong@clusterfs.com>
  */
 
 
@@ -83,18 +96,18 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
         struct mdt_device       *mdt = info->mti_mdt;
         struct ptlrpc_user_desc *pud = req->rq_user_desc;
         struct md_ucred         *ucred = mdt_ucred(info);
-        lnet_nid_t              peernid = req->rq_peer.nid;
+        lnet_nid_t               peernid = req->rq_peer.nid;
         __u32                    perm = 0;
-        int                     setuid;
-        int                     setgid;
-        int                     rc = 0;
+        int                      setuid;
+        int                      setgid;
+        int                      rc = 0;
 
         ENTRY;
 
         LASSERT(req->rq_auth_gss);
         LASSERT(!req->rq_auth_usr_mdt);
         LASSERT(req->rq_user_desc);
-        
+
         ucred->mu_valid = UCRED_INVALID;
 
         ucred->mu_o_uid   = pud->pud_uid;
@@ -112,7 +125,7 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
         /* sanity check: we expect the uid which client claimed is true */
         if (med->med_rmtclient) {
                 if (req->rq_auth_mapped_uid == INVALID_UID) {
-                        CWARN("remote user not mapped, deny access!\n");
+                        CDEBUG(D_SEC, "remote user not mapped, deny access!\n");
                         RETURN(-EACCES);
                 }
 
@@ -120,9 +133,9 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
                         RETURN(-EACCES);
 
                 if (req->rq_auth_mapped_uid != pud->pud_uid) {
-                        CERROR("remote client "LPU64": auth/mapped uid %u/%u "
-                               "while client claim %u:%u/%u:%u\n",
-                               peernid, req->rq_auth_uid,
+                        CDEBUG(D_SEC, "remote client %s: auth/mapped uid %u/%u "
+                               "while client claims %u:%u/%u:%u\n",
+                               libcfs_nid2str(peernid), req->rq_auth_uid,
                                req->rq_auth_mapped_uid,
                                pud->pud_uid, pud->pud_gid,
                                pud->pud_fsuid, pud->pud_fsgid);
@@ -130,17 +143,18 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
                 }
         } else {
                 if (req->rq_auth_uid != pud->pud_uid) {
-                        CERROR("local client "LPU64": auth uid %u "
-                               "while client claim %u:%u/%u:%u\n",
-                               peernid, req->rq_auth_uid, pud->pud_uid,
-                               pud->pud_gid, pud->pud_fsuid, pud->pud_fsgid);
+                        CDEBUG(D_SEC, "local client %s: auth uid %u "
+                               "while client claims %u:%u/%u:%u\n",
+                               libcfs_nid2str(peernid), req->rq_auth_uid,
+                               pud->pud_uid, pud->pud_gid,
+                               pud->pud_fsuid, pud->pud_fsgid);
                         RETURN(-EACCES);
                 }
         }
 
         if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
                 if (med->med_rmtclient) {
-                        CERROR("remote client must run with identity_get "
+                        CDEBUG(D_SEC, "remote client must run with identity_get "
                                "enabled!\n");
                         RETURN(-EACCES);
                 } else {
@@ -149,16 +163,26 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
                                CFS_SETGRP_PERM;
                 }
         } else {
-                ucred->mu_identity = mdt_identity_get(mdt->mdt_identity_cache,
-                                                      pud->pud_uid);
-                if (!ucred->mu_identity) {
-                        CERROR("Deny access without identity: uid %d\n",
-                               pud->pud_uid);
-                RETURN(-EACCES);
+                struct md_identity *identity;
+
+                identity = mdt_identity_get(mdt->mdt_identity_cache,
+                                            pud->pud_uid);
+                if (IS_ERR(identity)) {
+                        if (unlikely(PTR_ERR(identity) == -EREMCHG &&
+                                     !med->med_rmtclient)) {
+                                ucred->mu_identity = NULL;
+                                perm = CFS_SETUID_PERM | CFS_SETGID_PERM |
+                                       CFS_SETGRP_PERM;
+                        } else {
+                                CDEBUG(D_SEC, "Deny access without identity: uid %u\n",
+                                       pud->pud_uid);
+                                RETURN(-EACCES);
+                        }
                 } else {
+                        ucred->mu_identity = identity;
                         perm = mdt_identity_get_perm(ucred->mu_identity,
-                                                   med->med_rmtclient,
-                                                   peernid);
+                                                     med->med_rmtclient,
+                                                     peernid);
                 }
         }
 
@@ -170,17 +194,17 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
 
         /* check permission of setuid */
         if (setuid && !(perm & CFS_SETUID_PERM)) {
-                CWARN("mdt blocked setuid attempt (%u -> %u) from "
-                      LPX64"\n", pud->pud_uid, pud->pud_fsuid, peernid);
+                CDEBUG(D_SEC, "mdt blocked setuid attempt (%u -> %u) from %s\n",
+                       pud->pud_uid, pud->pud_fsuid, libcfs_nid2str(peernid));
                 GOTO(out, rc = -EACCES);
         }
 
         /* check permission of setgid */
         if (setgid && !(perm & CFS_SETGID_PERM)) {
-                CWARN("mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
-                      "from "LPX64"\n", pud->pud_uid, pud->pud_gid,
-                      pud->pud_fsuid, pud->pud_fsgid,
-                      ucred->mu_identity->mi_gid, peernid);
+                CDEBUG(D_SEC, "mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
+                       "from %s\n", pud->pud_uid, pud->pud_gid,
+                       pud->pud_fsuid, pud->pud_fsgid,
+                       ucred->mu_identity->mi_gid, libcfs_nid2str(peernid));
                 GOTO(out, rc = -EACCES);
         }
 
@@ -189,20 +213,20 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
          */
         if (!med->med_rmtclient && perm & CFS_SETGRP_PERM) {
                 if (pud->pud_ngroups) {
-                /* setgroups for local client */
+                        /* setgroups for local client */
                         ucred->mu_ginfo = groups_alloc(pud->pud_ngroups);
                         if (!ucred->mu_ginfo) {
-                        CERROR("failed to alloc %d groups\n",
-                               pud->pud_ngroups);
-                        GOTO(out, rc = -ENOMEM);
-                }
+                                CERROR("failed to alloc %d groups\n",
+                                       pud->pud_ngroups);
+                                GOTO(out, rc = -ENOMEM);
+                        }
 
                         lustre_groups_from_list(ucred->mu_ginfo,
                                                 pud->pud_groups);
                         lustre_groups_sort(ucred->mu_ginfo);
-        } else {
-                ucred->mu_ginfo = NULL;
-        }
+                } else {
+                        ucred->mu_ginfo = NULL;
+                }
         } else {
                 ucred->mu_suppgids[0] = -1;
                 ucred->mu_suppgids[1] = -1;
@@ -219,7 +243,7 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
 
         /* remove fs privilege for non-root user */
         if (ucred->mu_fsuid)
-                ucred->mu_cap = pud->pud_cap & ~CAP_FS_MASK;
+                ucred->mu_cap = pud->pud_cap & ~CFS_CAP_FS_MASK;
         else
                 ucred->mu_cap = pud->pud_cap;
         ucred->mu_valid = UCRED_NEW;
@@ -250,7 +274,7 @@ int mdt_check_ucred(struct mdt_thread_info *info)
         struct ptlrpc_user_desc *pud = req->rq_user_desc;
         struct md_ucred         *ucred = mdt_ucred(info);
         struct md_identity      *identity = NULL;
-        lnet_nid_t              peernid = req->rq_peer.nid;
+        lnet_nid_t               peernid = req->rq_peer.nid;
         __u32                    perm = 0;
         int                      setuid;
         int                      setgid;
@@ -266,38 +290,38 @@ int mdt_check_ucred(struct mdt_thread_info *info)
 
         /* sanity check: if we use strong authentication, we expect the
          * uid which client claimed is true */
-                if (med->med_rmtclient) {
-                        if (req->rq_auth_mapped_uid == INVALID_UID) {
-                                CWARN("remote user not mapped, deny access!\n");
-                                RETURN(-EACCES);
-                        }
+        if (med->med_rmtclient) {
+                if (req->rq_auth_mapped_uid == INVALID_UID) {
+                        CDEBUG(D_SEC, "remote user not mapped, deny access!\n");
+                        RETURN(-EACCES);
+                }
 
-                        if (ptlrpc_user_desc_do_idmap(req, pud))
-                                RETURN(-EACCES);
+                if (ptlrpc_user_desc_do_idmap(req, pud))
+                        RETURN(-EACCES);
 
-                        if (req->rq_auth_mapped_uid != pud->pud_uid) {
-                        CERROR("remote client "LPU64": auth/mapped uid %u/%u "
-                                       "while client claim %u:%u/%u:%u\n",
-                               peernid, req->rq_auth_uid,
+                if (req->rq_auth_mapped_uid != pud->pud_uid) {
+                        CDEBUG(D_SEC, "remote client %s: auth/mapped uid %u/%u "
+                               "while client claims %u:%u/%u:%u\n",
+                               libcfs_nid2str(peernid), req->rq_auth_uid,
                                req->rq_auth_mapped_uid,
                                pud->pud_uid, pud->pud_gid,
                                pud->pud_fsuid, pud->pud_fsgid);
-                                RETURN(-EACCES);
-                        }
-                } else {
-                        if (req->rq_auth_uid != pud->pud_uid) {
-                                CERROR("local client "LPU64": auth uid %u "
-                                       "while client claim %u:%u/%u:%u\n",
-                                       peernid, req->rq_auth_uid, pud->pud_uid,
-                                       pud->pud_gid, pud->pud_fsuid,
-                                       pud->pud_fsgid);
-                                RETURN(-EACCES);
-                        }
+                        RETURN(-EACCES);
+                }
+        } else {
+                if (req->rq_auth_uid != pud->pud_uid) {
+                        CDEBUG(D_SEC, "local client %s: auth uid %u "
+                               "while client claims %u:%u/%u:%u\n",
+                               libcfs_nid2str(peernid), req->rq_auth_uid,
+                               pud->pud_uid, pud->pud_gid,
+                               pud->pud_fsuid, pud->pud_fsgid);
+                        RETURN(-EACCES);
                 }
+        }
 
         if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
                 if (med->med_rmtclient) {
-                        CERROR("remote client must run with identity_get "
+                        CDEBUG(D_SEC, "remote client must run with identity_get "
                                "enabled!\n");
                         RETURN(-EACCES);
                 }
@@ -305,9 +329,15 @@ int mdt_check_ucred(struct mdt_thread_info *info)
         }
 
         identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid);
-        if (!identity) {
-                CERROR("Deny access without identity: uid %d\n", pud->pud_uid);
-                RETURN(-EACCES);
+        if (IS_ERR(identity)) {
+                if (unlikely(PTR_ERR(identity) == -EREMCHG &&
+                             !med->med_rmtclient)) {
+                        RETURN(0);
+                } else {
+                        CDEBUG(D_SEC, "Deny access without identity: uid %u\n",
+                               pud->pud_uid);
+                        RETURN(-EACCES);
+               }
         }
 
         perm = mdt_identity_get_perm(identity, med->med_rmtclient, peernid);
@@ -318,17 +348,17 @@ int mdt_check_ucred(struct mdt_thread_info *info)
 
         /* check permission of setuid */
         if (setuid && !(perm & CFS_SETUID_PERM)) {
-                CWARN("mdt blocked setuid attempt (%u -> %u) from "
-                      LPX64"\n", pud->pud_uid, pud->pud_fsuid, peernid);
+                CDEBUG(D_SEC, "mdt blocked setuid attempt (%u -> %u) from %s\n",
+                       pud->pud_uid, pud->pud_fsuid, libcfs_nid2str(peernid));
                 GOTO(out, rc = -EACCES);
         }
 
         /* check permission of setgid */
         if (setgid && !(perm & CFS_SETGID_PERM)) {
-                CWARN("mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
-                      "from "LPX64"\n", pud->pud_uid, pud->pud_gid,
-                      pud->pud_fsuid, pud->pud_fsgid, identity->mi_gid,
-                      peernid);
+                CDEBUG(D_SEC, "mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
+                       "from %s\n", pud->pud_uid, pud->pud_gid,
+                       pud->pud_fsuid, pud->pud_fsgid, identity->mi_gid,
+                       libcfs_nid2str(peernid));
                 GOTO(out, rc = -EACCES);
         }
 
@@ -359,10 +389,14 @@ static int old_init_ucred(struct mdt_thread_info *info,
         if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
                 identity = mdt_identity_get(mdt->mdt_identity_cache,
                                             uc->mu_fsuid);
-                if (!identity) {
-                        CERROR("Deny access without identity: uid %d\n",
-                               uc->mu_fsuid);
-                        RETURN(-EACCES);
+                if (IS_ERR(identity)) {
+                        if (unlikely(PTR_ERR(identity) == -EREMCHG)) {
+                                identity = NULL;
+                        } else {
+                                CDEBUG(D_SEC, "Deny access without identity: "
+                                       "uid %u\n", uc->mu_fsuid);
+                                RETURN(-EACCES);
+                        }
                 }
         }
         uc->mu_identity = identity;
@@ -372,7 +406,7 @@ static int old_init_ucred(struct mdt_thread_info *info,
 
         /* remove fs privilege for non-root user */
         if (uc->mu_fsuid)
-                uc->mu_cap = body->capability & ~CAP_FS_MASK;
+                uc->mu_cap = body->capability & ~CFS_CAP_FS_MASK;
         else
                 uc->mu_cap = body->capability;
         uc->mu_valid = UCRED_OLD;
@@ -395,11 +429,15 @@ static int old_init_ucred_reint(struct mdt_thread_info *info)
         if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
                 identity = mdt_identity_get(mdt->mdt_identity_cache,
                                             uc->mu_fsuid);
-                if (!identity) {
-                        CERROR("Deny access without identity: uid %d\n",
-                               uc->mu_fsuid);
-                        RETURN(-EACCES);
-        }
+                if (IS_ERR(identity)) {
+                        if (unlikely(PTR_ERR(identity) == -EREMCHG)) {
+                                identity = NULL;
+                        } else {
+                                CDEBUG(D_SEC, "Deny access without identity: "
+                                       "uid %u\n", uc->mu_fsuid);
+                                RETURN(-EACCES);
+                        }
+                }
         }
         uc->mu_identity = identity;
 
@@ -408,7 +446,7 @@ static int old_init_ucred_reint(struct mdt_thread_info *info)
 
         /* remove fs privilege for non-root user */
         if (uc->mu_fsuid)
-                uc->mu_cap &= ~CAP_FS_MASK;
+                uc->mu_cap &= ~CFS_CAP_FS_MASK;
         uc->mu_valid = UCRED_OLD;
 
         RETURN(0);
@@ -487,7 +525,7 @@ void mdt_shrink_reply(struct mdt_thread_info *info)
 
         acl_size = body->aclsize;
 
-        CDEBUG(D_INFO, "Shrink to md_size = %d cookie/acl_size = %d" 
+        CDEBUG(D_INFO, "Shrink to md_size = %d cookie/acl_size = %d"
                         " MDSCAPA = "LPX64", OSSCAPA = "LPX64"\n",
                         md_size, acl_size,
                         body->valid & OBD_MD_FLMDSCAPA,
@@ -508,14 +546,14 @@ void mdt_shrink_reply(struct mdt_thread_info *info)
                 req_capsule_shrink(pill, &RMF_ACL, acl_size, RCL_SERVER);
         else if (req_capsule_has_field(pill, &RMF_LOGCOOKIES, RCL_SERVER))
                 req_capsule_shrink(pill, &RMF_LOGCOOKIES,
-                                            acl_size, RCL_SERVER);
+                                   acl_size, RCL_SERVER);
 
         if (req_capsule_has_field(pill, &RMF_CAPA1, RCL_SERVER) &&
-                    !(body->valid & OBD_MD_FLMDSCAPA))
+            !(body->valid & OBD_MD_FLMDSCAPA))
                 req_capsule_shrink(pill, &RMF_CAPA1, 0, RCL_SERVER);
 
         if (req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) &&
-                !(body->valid & OBD_MD_FLOSSCAPA))
+            !(body->valid & OBD_MD_FLOSSCAPA))
                 req_capsule_shrink(pill, &RMF_CAPA2, 0, RCL_SERVER);
 
         /*
@@ -643,7 +681,10 @@ static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr,
                 out |= LA_FLAGS;
 
         if (in & MDS_OPEN_OWNEROVERRIDE)
-                out |= MDS_OPEN_OWNEROVERRIDE;
+                ma->ma_attr_flags |= MDS_OPEN_OWNEROVERRIDE;
+
+        if (in & (ATTR_KILL_SUID|ATTR_KILL_SGID))
+                ma->ma_attr_flags |= MDS_PERM_BYPASS;
 
         /*XXX need ATTR_RAW?*/
         in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS|
@@ -717,7 +758,7 @@ static inline int mdt_dlmreq_unpack(struct mdt_thread_info *info) {
                 if (info->mti_dlm_req == NULL)
                         RETURN(-EFAULT);
         }
-        
+
         RETURN(0);
 }
 
@@ -810,7 +851,7 @@ static int mdt_create_unpack(struct mdt_thread_info *info)
         rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
         rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
         LASSERT(rr->rr_name && rr->rr_namelen > 0);
-        
+
 #ifdef CONFIG_FS_POSIX_ACL
         if (sp->sp_cr_flags & MDS_CREATE_RMT_ACL) {
                 if (S_ISDIR(attr->la_mode))
@@ -1113,11 +1154,13 @@ static int mdt_setxattr_unpack(struct mdt_thread_info *info)
         uc->mu_fsuid  = rec->sx_fsuid;
         uc->mu_fsgid  = rec->sx_fsgid;
         uc->mu_cap    = rec->sx_cap;
-        uc->mu_suppgids[0] = uc->mu_suppgids[1] = -1;
+        uc->mu_suppgids[0] = rec->sx_suppgid1;
+        uc->mu_suppgids[1] = -1;
 
         rr->rr_opcode = rec->sx_opcode;
         rr->rr_fid1   = &rec->sx_fid;
         attr->la_valid = rec->sx_valid;
+        attr->la_ctime = rec->sx_time;
         attr->la_size = rec->sx_size;
         attr->la_flags = rec->sx_flags;