@@ -5603,6 +5603,170 @@ void send_flush_mdlog(struct ceph_mds_session *s)
56035603 mutex_unlock (& s -> s_mutex );
56045604}
56055605
5606+ static int ceph_mds_auth_match (struct ceph_mds_client * mdsc ,
5607+ struct ceph_mds_cap_auth * auth ,
5608+ char * tpath )
5609+ {
5610+ const struct cred * cred = get_current_cred ();
5611+ u32 caller_uid = from_kuid (& init_user_ns , cred -> fsuid );
5612+ u32 caller_gid = from_kgid (& init_user_ns , cred -> fsgid );
5613+ struct ceph_client * cl = mdsc -> fsc -> client ;
5614+ const char * spath = mdsc -> fsc -> mount_options -> server_path ;
5615+ bool gid_matched = false;
5616+ u32 gid , tlen , len ;
5617+ int i , j ;
5618+
5619+ doutc (cl , "match.uid %lld\n" , auth -> match .uid );
5620+ if (auth -> match .uid != MDS_AUTH_UID_ANY ) {
5621+ if (auth -> match .uid != caller_uid )
5622+ return 0 ;
5623+ if (auth -> match .num_gids ) {
5624+ for (i = 0 ; i < auth -> match .num_gids ; i ++ ) {
5625+ if (caller_gid == auth -> match .gids [i ])
5626+ gid_matched = true;
5627+ }
5628+ if (!gid_matched && cred -> group_info -> ngroups ) {
5629+ for (i = 0 ; i < cred -> group_info -> ngroups ; i ++ ) {
5630+ gid = from_kgid (& init_user_ns ,
5631+ cred -> group_info -> gid [i ]);
5632+ for (j = 0 ; j < auth -> match .num_gids ; j ++ ) {
5633+ if (gid == auth -> match .gids [j ]) {
5634+ gid_matched = true;
5635+ break ;
5636+ }
5637+ }
5638+ if (gid_matched )
5639+ break ;
5640+ }
5641+ }
5642+ if (!gid_matched )
5643+ return 0 ;
5644+ }
5645+ }
5646+
5647+ /* path match */
5648+ if (auth -> match .path ) {
5649+ if (!tpath )
5650+ return 0 ;
5651+
5652+ tlen = strlen (tpath );
5653+ len = strlen (auth -> match .path );
5654+ if (len ) {
5655+ char * _tpath = tpath ;
5656+ bool free_tpath = false;
5657+ int m , n ;
5658+
5659+ doutc (cl , "server path %s, tpath %s, match.path %s\n" ,
5660+ spath , tpath , auth -> match .path );
5661+ if (spath && (m = strlen (spath )) != 1 ) {
5662+ /* mount path + '/' + tpath + an extra space */
5663+ n = m + 1 + tlen + 1 ;
5664+ _tpath = kmalloc (n , GFP_NOFS );
5665+ if (!_tpath )
5666+ return - ENOMEM ;
5667+ /* remove the leading '/' */
5668+ snprintf (_tpath , n , "%s/%s" , spath + 1 , tpath );
5669+ free_tpath = true;
5670+ tlen = strlen (_tpath );
5671+ }
5672+
5673+ /*
5674+ * Please note the tailing '/' for match.path has already
5675+ * been removed when parsing.
5676+ *
5677+ * Remove the tailing '/' for the target path.
5678+ */
5679+ while (tlen && _tpath [tlen - 1 ] == '/' ) {
5680+ _tpath [tlen - 1 ] = '\0' ;
5681+ tlen -= 1 ;
5682+ }
5683+ doutc (cl , "_tpath %s\n" , _tpath );
5684+
5685+ /*
5686+ * In case first == _tpath && tlen == len:
5687+ * match.path=/foo --> /foo _path=/foo --> match
5688+ * match.path=/foo/ --> /foo _path=/foo --> match
5689+ *
5690+ * In case first == _tmatch.path && tlen > len:
5691+ * match.path=/foo/ --> /foo _path=/foo/ --> match
5692+ * match.path=/foo --> /foo _path=/foo/ --> match
5693+ * match.path=/foo/ --> /foo _path=/foo/d --> match
5694+ * match.path=/foo --> /foo _path=/food --> mismatch
5695+ *
5696+ * All the other cases --> mismatch
5697+ */
5698+ char * first = strstr (_tpath , auth -> match .path );
5699+ if (first != _tpath ) {
5700+ if (free_tpath )
5701+ kfree (_tpath );
5702+ return 0 ;
5703+ }
5704+
5705+ if (tlen > len && _tpath [len ] != '/' ) {
5706+ if (free_tpath )
5707+ kfree (_tpath );
5708+ return 0 ;
5709+ }
5710+ }
5711+ }
5712+
5713+ doutc (cl , "matched\n" );
5714+ return 1 ;
5715+ }
5716+
5717+ int ceph_mds_check_access (struct ceph_mds_client * mdsc , char * tpath , int mask )
5718+ {
5719+ const struct cred * cred = get_current_cred ();
5720+ u32 caller_uid = from_kuid (& init_user_ns , cred -> fsuid );
5721+ u32 caller_gid = from_kgid (& init_user_ns , cred -> fsgid );
5722+ struct ceph_mds_cap_auth * rw_perms_s = NULL ;
5723+ struct ceph_client * cl = mdsc -> fsc -> client ;
5724+ bool root_squash_perms = true;
5725+ int i , err ;
5726+
5727+ doutc (cl , "tpath '%s', mask %d, caller_uid %d, caller_gid %d\n" ,
5728+ tpath , mask , caller_uid , caller_gid );
5729+
5730+ for (i = 0 ; i < mdsc -> s_cap_auths_num ; i ++ ) {
5731+ struct ceph_mds_cap_auth * s = & mdsc -> s_cap_auths [i ];
5732+
5733+ err = ceph_mds_auth_match (mdsc , s , tpath );
5734+ if (err < 0 ) {
5735+ return err ;
5736+ } else if (err > 0 ) {
5737+ /* always follow the last auth caps' permision */
5738+ root_squash_perms = true;
5739+ rw_perms_s = NULL ;
5740+ if ((mask & MAY_WRITE ) && s -> writeable &&
5741+ s -> match .root_squash && (!caller_uid || !caller_gid ))
5742+ root_squash_perms = false;
5743+
5744+ if (((mask & MAY_WRITE ) && !s -> writeable ) ||
5745+ ((mask & MAY_READ ) && !s -> readable ))
5746+ rw_perms_s = s ;
5747+ }
5748+ }
5749+
5750+ doutc (cl , "root_squash_perms %d, rw_perms_s %p\n" , root_squash_perms ,
5751+ rw_perms_s );
5752+ if (root_squash_perms && rw_perms_s == NULL ) {
5753+ doutc (cl , "access allowed\n" );
5754+ return 0 ;
5755+ }
5756+
5757+ if (!root_squash_perms ) {
5758+ doutc (cl , "root_squash is enabled and user(%d %d) isn't allowed to write" ,
5759+ caller_uid , caller_gid );
5760+ }
5761+ if (rw_perms_s ) {
5762+ doutc (cl , "mds auth caps readable/writeable %d/%d while request r/w %d/%d" ,
5763+ rw_perms_s -> readable , rw_perms_s -> writeable ,
5764+ !!(mask & MAY_READ ), !!(mask & MAY_WRITE ));
5765+ }
5766+ doutc (cl , "access denied\n" );
5767+ return - EACCES ;
5768+ }
5769+
56065770/*
56075771 * called before mount is ro, and before dentries are torn down.
56085772 * (hmm, does this still race with new lookups?)
0 commit comments