[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