[Pvfs2-cvs] commit by kunkel in pvfs2/src/server: get-eattr.sm list-eattr.sm lookup.sm prelude.sm pvfs2-server.c pvfs2-server.h

CVS commit program cvs at parl.clemson.edu
Tue Aug 29 06:41:26 EDT 2006


Update of /projects/cvsroot/pvfs2/src/server
In directory parlweb1:/tmp/cvs-serv30492/src/server

Modified Files:
      Tag: kunkel-branch
	get-eattr.sm list-eattr.sm lookup.sm prelude.sm pvfs2-server.c 
	pvfs2-server.h 
Log Message:
Backmerge with HEAD


Index: get-eattr.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/get-eattr.sm,v
diff -p -u -r1.11 -r1.11.2.1
--- get-eattr.sm	13 Jul 2006 05:11:42 -0000	1.11
+++ get-eattr.sm	29 Aug 2006 10:41:25 -0000	1.11.2.1
@@ -21,7 +21,6 @@
 #include "pvfs2-server.h"
 #include "pvfs2-attr.h"
 #include "pvfs2-types.h"
-#include "pvfs2-types-debug.h"
 #include "pvfs2-util.h"
 #include "pint-util.h"
 
@@ -115,6 +114,8 @@ static int geteattr_setup_resp(PINT_serv
     /* iterate through the keys and see if they fall into valid name spaces */
     for(i=0; i<s_op->req->u.geteattr.nkey; i++)
     {
+        gossip_debug(GOSSIP_GETEATTR_DEBUG, "geteattr key %d : %s\n", i, 
+                (char *) s_op->req->u.geteattr.key[i].buffer);
         if(!PINT_eattr_is_prefixed(s_op->req->u.geteattr.key[i].buffer))
         {
             /* not prefixed: treat this as if the key does not exist */

Index: list-eattr.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/list-eattr.sm,v
diff -p -u -r1.6 -r1.6.2.1
--- list-eattr.sm	13 Jul 2006 05:11:42 -0000	1.6
+++ list-eattr.sm	29 Aug 2006 10:41:26 -0000	1.6.2.1
@@ -21,7 +21,6 @@
 #include "pvfs2-server.h"
 #include "pvfs2-attr.h"
 #include "pvfs2-types.h"
-#include "pvfs2-types-debug.h"
 #include "pvfs2-util.h"
 #include "pint-util.h"
 

Index: lookup.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/lookup.sm,v
diff -p -u -r1.46 -r1.46.2.1
--- lookup.sm	13 Jul 2006 05:11:42 -0000	1.46
+++ lookup.sm	29 Aug 2006 10:41:26 -0000	1.46.2.1
@@ -23,7 +23,8 @@
 enum 
 {
     STATE_ENOTDIR = 22,
-    STATE_NOMORESEGS = 23
+    STATE_NOMORESEGS = 23,
+    LOOKUP_CHECK_DIR_ACLS = 24,
 };
 
 static int lookup_init(
@@ -34,6 +35,10 @@ static int lookup_read_object_metadata(
     PINT_server_op *s_op, job_status_s* js_p);
 static int lookup_verify_object_metadata(
     PINT_server_op *s_op, job_status_s* js_p);
+static int lookup_check_acls_if_needed(
+    PINT_server_op *s_op, job_status_s* js_p);
+static int lookup_check_acls(
+    PINT_server_op *s_op, job_status_s* js_p);
 static int lookup_read_directory_entry(
     PINT_server_op *s_op, job_status_s* js_p);
 static int lookup_read_directory_entry_handle(
@@ -52,6 +57,8 @@ machine pvfs2_lookup_sm(
     read_directory_entry_handle,
     read_directory_entry,
     verify_object_metadata,
+    read_directory_acls,
+    check_acls,
     setup_resp,
     final_response,
     cleanup)
@@ -80,6 +87,20 @@ machine pvfs2_lookup_sm(
     state verify_object_metadata
     {
         run lookup_verify_object_metadata;
+        LOOKUP_CHECK_DIR_ACLS => read_directory_acls;
+        success => read_directory_entry_handle;
+        default => setup_resp;
+    }
+
+    state read_directory_acls
+    {
+        run lookup_check_acls_if_needed;
+        default => check_acls;
+    }
+
+    state check_acls
+    {
+        run lookup_check_acls;
         success => read_directory_entry_handle;
         default => setup_resp;
     }
@@ -161,7 +182,11 @@ static int lookup_init(PINT_server_op *s
     /* allocate the internal ds_attr_array */
     s_op->u.lookup.ds_attr_array = (PVFS_ds_attributes *)
         malloc(s_op->u.lookup.seg_ct * sizeof(PVFS_ds_attributes));
-    assert(s_op->u.lookup.ds_attr_array);
+    if(!s_op->u.lookup.ds_attr_array)
+    {
+        js_p->error_code = -PVFS_ENOMEM;
+        return 1;
+    }
 
     /* allocate memory
      *
@@ -225,6 +250,10 @@ static int lookup_read_object_metadata(
     /* update our successful handle read count */
     s_op->u.lookup.handle_ct++;
 
+    /* Copy the fsid and handle to the s_op structure for the acl check */
+    s_op->target_handle = handle;
+    s_op->target_fs_id = s_op->req->u.lookup_path.fs_id;
+
     /* get the dspace attributes/metadata */
     ret = job_trove_dspace_getattr(
         s_op->req->u.lookup_path.fs_id, handle, s_op, ds_attr,
@@ -270,6 +299,7 @@ static int lookup_verify_object_metadata
 
     PVFS_ds_attr_to_object_attr(ds_attr, a_p);
     a_p->mask = PVFS_ATTR_COMMON_ALL;
+    s_op->target_object_attr = a_p;
 
     /* update our successful attr read count */
     s_op->u.lookup.attr_ct++;
@@ -326,6 +356,7 @@ static int lookup_verify_object_metadata
         /* doesn't look like we have permission to traverse directory; bail
          * out
          */
+        js_p->error_code = LOOKUP_CHECK_DIR_ACLS;
         return(1);
     }
 
@@ -334,6 +365,11 @@ static int lookup_verify_object_metadata
         s_op->req->u.lookup_path.path, &s_op->u.lookup.segp,
         &s_op->u.lookup.segstate);
 
+    if(ret != 0)
+    {
+        gossip_err("PINT_string_next_segment failed: path: %s\n",
+                   s_op->req->u.lookup_path.path);
+    }
     assert(ret == 0);
 
     gossip_debug(GOSSIP_SERVER_DEBUG, "  object is a directory; will be "
@@ -341,6 +377,108 @@ static int lookup_verify_object_metadata
 		 s_op->u.lookup.segp);
 
 
+    return 1;
+}
+
+/*
+ * Post a keyval DB read of the posix acls to check and see if 
+ * directory traversal is allowed or not
+ */
+static int lookup_check_acls_if_needed(
+    PINT_server_op *s_op, job_status_s* js_p)
+{
+    int ret = -PVFS_EINVAL;
+    job_id_t i;
+
+    /* If we get here with an invalid fsid and handle, we have to
+     * return -PVFS_EACCESS 
+     */
+    if (s_op->target_fs_id == PVFS_FS_ID_NULL
+        || s_op->target_handle == PVFS_HANDLE_NULL)
+    {
+        js_p->error_code = -PVFS_EACCES;
+        return 1;
+    }
+    js_p->error_code = 0;
+
+    memset(&s_op->key, 0, sizeof(PVFS_ds_keyval));
+    memset(&s_op->val, 0, sizeof(PVFS_ds_keyval));
+    s_op->key.buffer = "system.posix_acl_access";
+    s_op->key.buffer_sz = strlen(s_op->key.buffer) + 1;
+    s_op->val.buffer = (char *) malloc(PVFS_REQ_LIMIT_VAL_LEN);
+    if (!s_op->val.buffer)
+    {
+        js_p->error_code = -PVFS_ENOMEM;
+        return 1;
+    }
+    s_op->val.buffer_sz = PVFS_REQ_LIMIT_VAL_LEN;
+
+    gossip_debug(GOSSIP_PERMISSIONS_DEBUG, "About to retrieve acl keyvals "
+                 "for handle %llu\n", llu(s_op->target_handle));
+
+    /* Read acl keys */
+    ret = job_trove_keyval_read(
+        s_op->target_fs_id,
+        s_op->target_handle,
+        &s_op->key,
+        &s_op->val,
+        0,
+        NULL,
+        s_op,
+        0,
+        js_p,
+        &i,
+        server_job_context);
+    return ret;
+}
+
+/*
+ * Verify if the completed keyval DB operation allows the lookup
+ * to proceed or not. i.e. executable privileges on directory
+ * for the requesting user or not.
+ */
+static int lookup_check_acls(
+    PINT_server_op *s_op, job_status_s* js_p)
+{
+    PVFS_object_attr *obj_attr = NULL;
+    int want = PVFS2_ACL_EXECUTE;
+
+    /* The dspace attr must have been read at this point */
+    obj_attr = s_op->target_object_attr;
+    assert(obj_attr);
+
+    /* anything non-zero we treat as a real error */
+    if (js_p->error_code)
+    {
+        goto cleanup;
+    }
+    /* ok; let the actual acl check be done */
+    js_p->error_code = PINT_check_acls(s_op->val.buffer,
+                        s_op->val.read_sz,
+                        obj_attr, 
+                        s_op->req->credentials.uid,
+                        s_op->req->credentials.gid,
+                        want);
+    /* if we are good to go,
+       find the segment that we should look up in the directory */
+    if (js_p->error_code == 0)
+    {
+        int ret = PINT_string_next_segment(
+            s_op->req->u.lookup_path.path, &s_op->u.lookup.segp,
+            &s_op->u.lookup.segstate);
+
+        assert(ret == 0);
+
+        gossip_debug(GOSSIP_SERVER_DEBUG, "  after ACL check "
+                    "object is a directory; will be "
+                     "looking for handle for segment \"%s\" in a bit\n",
+                     s_op->u.lookup.segp);
+    }
+cleanup:
+    if (s_op->val.buffer) 
+        free(s_op->val.buffer);
+    memset(&s_op->key, 0, sizeof(PVFS_ds_keyval));
+    memset(&s_op->val, 0, sizeof(PVFS_ds_keyval));
     return 1;
 }
 

Index: prelude.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/prelude.sm,v
diff -p -u -r1.60.6.1 -r1.60.6.2
--- prelude.sm	26 Aug 2006 13:37:48 -0000	1.60.6.1
+++ prelude.sm	29 Aug 2006 10:41:26 -0000	1.60.6.2
@@ -29,15 +29,25 @@ static int prelude_perm_check(
     PINT_server_op *s_op, job_status_s *js_p);
 static int prelude_getattr_if_needed(
     PINT_server_op *s_op, job_status_s *js_p);
+static int prelude_check_acls_if_needed(
+    PINT_server_op *s_op, job_status_s *js_p);
+static int prelude_check_acls(
+    PINT_server_op *s_op, job_status_s *js_p);
 
 extern PINT_server_trove_keys_s Trove_Common_Keys[];
 
+enum {
+    PRELUDE_RUN_ACL_CHECKS = 1,
+};
+
 %%
 
 nested machine pvfs2_prelude_sm(
     req_sched,
     getattr_if_needed,
-    perm_check)
+    perm_check,
+    check_acls_if_needed,
+    check_acls)
 {
     state req_sched
     {
@@ -55,6 +65,19 @@ nested machine pvfs2_prelude_sm(
     state perm_check
     {
         run prelude_perm_check;
+        PRELUDE_RUN_ACL_CHECKS => check_acls_if_needed;
+        default => return;
+    }
+
+    state check_acls_if_needed
+    {
+        run prelude_check_acls_if_needed;
+        default => check_acls;
+    }
+
+    state check_acls
+    {
+        run prelude_check_acls;
         default => return;
     }
 }
@@ -108,8 +131,6 @@ static int prelude_getattr_if_needed(
     PINT_server_op *s_op, job_status_s *js_p)
 {
     int ret = -PVFS_EINVAL, readonly_flag = 0;
-    PVFS_handle target_handle = PVFS_HANDLE_NULL;
-    PVFS_fs_id target_fs_id = PVFS_FS_ID_NULL;
     job_id_t tmp_id;
 
     PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DETAIL_DEBUG, "start\n");
@@ -122,13 +143,14 @@ static int prelude_getattr_if_needed(
      * what handle this request will operate on
      */
     ret = PINT_req_sched_target_handle(
-        s_op->req, 0, &target_handle, &target_fs_id, &readonly_flag);
+        s_op->req, 0, &s_op->target_handle, 
+        &s_op->target_fs_id, &readonly_flag);
 
     if (ret < 0)
     {
         gossip_debug(GOSSIP_SERVER_DEBUG, "PINT_req_sched_target_handle "
                      "returned %d ret, skipping getattr on handle %llu\n",
-                     ret, llu(target_handle));
+                     ret, llu(s_op->target_handle));
 
         js_p->error_code = ret;
         return 1;
@@ -138,7 +160,7 @@ static int prelude_getattr_if_needed(
      * operate on a specific handle, so there is nothing we can do
      * here
      */
-    if (target_handle == PVFS_HANDLE_NULL)
+    if (s_op->target_handle == PVFS_HANDLE_NULL)
     {
         js_p->error_code = 0;
         return 1;
@@ -150,10 +172,11 @@ static int prelude_getattr_if_needed(
     memset(&(s_op->ds_attr), 0, sizeof(PVFS_ds_attributes));
 
     gossip_debug(GOSSIP_SERVER_DEBUG, "About to retrieve attributes "
-                 "for handle %llu\n", llu(target_handle));
+                 "for handle %llu\n", llu(s_op->target_handle));
 
     ret = job_trove_dspace_getattr(
-        target_fs_id, target_handle, s_op, &(s_op->ds_attr),
+        s_op->target_fs_id, s_op->target_handle,
+        s_op, &(s_op->ds_attr),
         0, js_p, &tmp_id, server_job_context);
 
     return ret;
@@ -183,6 +206,8 @@ static int prelude_perm_check(
     obj_attr = &s_op->attr;
     PVFS_ds_attr_to_object_attr(ds_attr, obj_attr);
     s_op->attr.mask = PVFS_ATTR_COMMON_ALL;
+    /* Set the target object attribute pointer.. used later by the acl check */
+    s_op->target_object_attr = obj_attr;
 
     /* Commenting out the below block for now.  I think this code is
      * deprecated?  Even if not all of the attributes have been filled in
@@ -284,7 +309,7 @@ static int prelude_perm_check(
                 }
                 else
                 {
-                    js_p->error_code = -PVFS_EPERM;
+                    js_p->error_code = -PVFS_EACCES;
                 }
             }
             break;
@@ -306,6 +331,126 @@ static int prelude_perm_check(
 	s_op,
         PINT_map_server_op_to_string(s_op->req->op),
 	js_p->error_code);
+    /* If regular checks fail, we need to run acl checks */
+    if (js_p->error_code == -PVFS_EACCES)
+        js_p->error_code = PRELUDE_RUN_ACL_CHECKS;
+    return 1;
+}
+
+
+static int prelude_check_acls_if_needed(
+    PINT_server_op *s_op, job_status_s *js_p)
+{
+    int ret = -PVFS_EINVAL;
+    job_id_t i;
+
+    gossip_debug(GOSSIP_SERVER_DEBUG,
+                 "(%p) %s (prelude sm) state: prelude_check_acls_if_needed\n", s_op,
+                 PINT_map_server_op_to_string(s_op->req->op));
+
+    /* If we get here with an invalid fsid and handle, we have to
+     * return -PVFS_EACCESS 
+     */
+    if (s_op->target_fs_id == PVFS_FS_ID_NULL
+        || s_op->target_handle == PVFS_HANDLE_NULL)
+    {
+        js_p->error_code = -PVFS_EACCES;
+        return 1;
+    }
+    js_p->error_code = 0;
+
+    memset(&s_op->key, 0, sizeof(PVFS_ds_keyval));
+    memset(&s_op->val, 0, sizeof(PVFS_ds_keyval));
+    s_op->key.buffer = "system.posix_acl_access";
+    s_op->key.buffer_sz = strlen(s_op->key.buffer) + 1;
+    s_op->val.buffer = (char *) malloc(PVFS_REQ_LIMIT_VAL_LEN);
+    if (!s_op->val.buffer)
+    {
+        js_p->error_code = -PVFS_ENOMEM;
+        return 1;
+    }
+    s_op->val.buffer_sz = PVFS_REQ_LIMIT_VAL_LEN;
+
+    gossip_debug(GOSSIP_PERMISSIONS_DEBUG, "About to retrieve acl keyvals "
+                 "for handle %llu\n", llu(s_op->target_handle));
+
+    /* Read acl keys */
+    ret = job_trove_keyval_read(
+        s_op->target_fs_id,
+        s_op->target_handle,
+        &s_op->key,
+        &s_op->val,
+        0,
+        NULL,
+        s_op,
+        0,
+        js_p,
+        &i,
+        server_job_context);
+    return ret;
+}
+
+static int prelude_check_acls(
+    PINT_server_op *s_op, job_status_s *js_p)
+{
+    PVFS_object_attr *obj_attr = NULL;
+    int want = 0;
+
+    /* The dspace attr must have been read at this point */
+    obj_attr = s_op->target_object_attr;
+    assert(obj_attr);
+
+    /* anything non-zero we treat as a real error */
+    if (js_p->error_code)
+    {
+        goto cleanup;
+    }
+    /* make sure that we hit here only for metafiles, dirs and symlink objects */
+    if (obj_attr->objtype != PVFS_TYPE_METAFILE
+        && obj_attr->objtype != PVFS_TYPE_DIRECTORY
+        && obj_attr->objtype != PVFS_TYPE_SYMLINK)
+    {
+        gossip_err("prelude_check_acls hit invalid object type %d\n",
+            obj_attr->objtype);
+        js_p->error_code = -PVFS_EINVAL;
+        goto cleanup;
+    }
+    switch (PINT_server_req_table[s_op->req->op].perm)
+    {
+        case PINT_SERVER_CHECK_WRITE:
+        default:
+            want = PVFS2_ACL_WRITE;
+            break;
+        case PINT_SERVER_CHECK_READ:
+            want = PVFS2_ACL_READ;
+            break;
+        case PINT_SERVER_CHECK_CRDIRENT:
+            want = PVFS2_ACL_WRITE | PVFS2_ACL_EXECUTE;
+            break;
+        case PINT_SERVER_CHECK_NONE:
+            want = 0;
+            break;
+        case PINT_SERVER_CHECK_INVALID:
+            js_p->error_code = -PVFS_EINVAL;
+            goto cleanup;
+    }
+    js_p->error_code = PINT_check_acls(s_op->val.buffer,
+                        s_op->val.read_sz,
+                        obj_attr, 
+                        s_op->req->credentials.uid,
+                        s_op->req->credentials.gid,
+                        want);
+cleanup:
+    gossip_debug(
+        GOSSIP_PERMISSIONS_DEBUG, "Final permission check (after acls) \"%s\" set "
+        "error code to %d (want %x)\n",
+            PINT_map_server_op_to_string(s_op->req->op),
+            js_p->error_code, want);
+
+    if (s_op->val.buffer) 
+        free(s_op->val.buffer);
+    memset(&s_op->key, 0, sizeof(PVFS_ds_keyval));
+    memset(&s_op->val, 0, sizeof(PVFS_ds_keyval));
     return 1;
 }
 

Index: pvfs2-server.c
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/pvfs2-server.c,v
diff -p -u -r1.218.2.8 -r1.218.2.9
--- pvfs2-server.c	26 Aug 2006 19:31:02 -0000	1.218.2.8
+++ pvfs2-server.c	29 Aug 2006 10:41:26 -0000	1.218.2.9
@@ -654,7 +654,6 @@ int main(int argc, char **argv)
                 if (ret < 0)
                 {
                     PVFS_perror_gossip("Error: server_state_machine_start", ret);
-                    free(s_op->unexp_bmi_buff.buffer);
                     /* TODO: tell BMI to drop this address? */
                     /* set return code to zero to allow server to continue
                      * processing 
@@ -997,6 +996,14 @@ static int server_initialize_subsystems(
         &server_config.trove_max_concurrent_io);
     /* this should never fail */
     assert(ret == 0);
+    ret = trove_collection_setinfo(0, 0, TROVE_ALT_AIO_MODE,
+        &server_config.trove_alt_aio_mode);
+    /* this should never fail */
+    assert(ret == 0);
+    ret = trove_collection_setinfo(0, 0, TROVE_MAX_CONCURRENT_IO,
+        &server_config.trove_max_concurrent_io);
+    /* this should never fail */
+    assert(ret == 0);
 
     /* parse port number and allow trove to use it to help differentiate
      * shmem regions if needed
@@ -1744,9 +1751,11 @@ static int server_post_unexpected_recv(j
         }
         memset(s_op, 0, sizeof(PINT_server_op));
         s_op->op = BMI_UNEXPECTED_OP;
+        s_op->target_handle = PVFS_HANDLE_NULL;
+        s_op->target_fs_id = PVFS_FS_ID_NULL;
         /* Add an unexpected s_ops to the list */
         qlist_add_tail(&s_op->next, &posted_sop_list);
-
+        
         /*
           TODO: Consider the optimization of enabling immediate
           completion in this part of the code (see the mailing list
@@ -1816,6 +1825,10 @@ static int server_state_machine_start(
                       s_op->unexp_bmi_buff.addr,
                       s_op->unexp_bmi_buff.size);
 
+    /* acknowledge that the unexpected buffer has been used up.
+     * If *someone* decides to do in-place decoding, then we will have to move
+     * this back to state_machine_complete().
+     */
     s_op->req  = (struct PVFS_server_req *)s_op->decoded.buffer;
     if (ret == -PVFS_EPROTONOSUPPORT)
     {
@@ -1881,6 +1894,10 @@ int server_state_machine_alloc_noreq(
         }
         memset(*new_op, 0, sizeof(PINT_server_op));
         (*new_op)->op = op;
+        (*new_op)->target_handle = PVFS_HANDLE_NULL;
+        (*new_op)->target_fs_id = PVFS_FS_ID_NULL;
+
+        /* NOTE: We do not add these state machines to the in-progress or posted sop lists */
 
         /* NOTE: We do not add these state machines to the in-progress or posted sop lists */
 
@@ -1968,11 +1985,12 @@ int server_state_machine_complete(PINT_s
         PINT_decode_release(&(s_op->decoded),PINT_DECODE_REQ);
     }
 
-    /* free the buffer that the unexpected request came in on */
-    if (s_op->unexp_bmi_buff.buffer)
-    {
-        free(s_op->unexp_bmi_buff.buffer);
-    }
+    BMI_unexpected_free(s_op->unexp_bmi_buff.addr, 
+                        s_op->unexp_bmi_buff.buffer);
+    s_op->unexp_bmi_buff.buffer = NULL;
+
+   /* Remove s_op from the inprogress_sop_list */
+    qlist_del(&s_op->next);
 
     /* Remove s_op from the inprogress_sop_list */
     qlist_del(&s_op->next);

Index: pvfs2-server.h
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/pvfs2-server.h,v
diff -p -u -r1.135.2.3 -r1.135.2.4
--- pvfs2-server.h	26 Aug 2006 13:37:48 -0000	1.135.2.3
+++ pvfs2-server.h	29 Aug 2006 10:41:26 -0000	1.135.2.4
@@ -399,6 +399,10 @@ typedef struct PINT_server_op
     PINT_sm_msgpair_state *msgarray;
     PINT_sm_msgpair_params msgarray_params;
 
+    PVFS_handle target_handle;
+    PVFS_fs_id target_fs_id;
+    PVFS_object_attr *target_object_attr;
+
     union
     {
 	/* request-specific scratch spaces for use during processing */



More information about the Pvfs2-cvs mailing list