@@ -5603,6 +5603,170 @@ void send_flush_mdlog(struct ceph_mds_session *s)
5603
5603
mutex_unlock (& s -> s_mutex );
5604
5604
}
5605
5605
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
+
5606
5770
/*
5607
5771
* called before mount is ro, and before dentries are torn down.
5608
5772
* (hmm, does this still race with new lookups?)
0 commit comments