@@ -4112,10 +4112,13 @@ static void handle_session(struct ceph_mds_session *session,
41124112 void * p = msg -> front .iov_base ;
41134113 void * end = p + msg -> front .iov_len ;
41144114 struct ceph_mds_session_head * h ;
4115- u32 op ;
4115+ struct ceph_mds_cap_auth * cap_auths = NULL ;
4116+ u32 op , cap_auths_num = 0 ;
41164117 u64 seq , features = 0 ;
41174118 int wake = 0 ;
41184119 bool blocklisted = false;
4120+ u32 i ;
4121+
41194122
41204123 /* decode */
41214124 ceph_decode_need (& p , end , sizeof (* h ), bad );
@@ -4160,7 +4163,101 @@ static void handle_session(struct ceph_mds_session *session,
41604163 }
41614164 }
41624165
4166+ if (msg_version >= 6 ) {
4167+ ceph_decode_32_safe (& p , end , cap_auths_num , bad );
4168+ doutc (cl , "cap_auths_num %d\n" , cap_auths_num );
4169+
4170+ if (cap_auths_num && op != CEPH_SESSION_OPEN ) {
4171+ WARN_ON_ONCE (op != CEPH_SESSION_OPEN );
4172+ goto skip_cap_auths ;
4173+ }
4174+
4175+ cap_auths = kcalloc (cap_auths_num ,
4176+ sizeof (struct ceph_mds_cap_auth ),
4177+ GFP_KERNEL );
4178+ if (!cap_auths ) {
4179+ pr_err_client (cl , "No memory for cap_auths\n" );
4180+ return ;
4181+ }
4182+
4183+ for (i = 0 ; i < cap_auths_num ; i ++ ) {
4184+ u32 _len , j ;
4185+
4186+ /* struct_v, struct_compat, and struct_len in MDSCapAuth */
4187+ ceph_decode_skip_n (& p , end , 2 + sizeof (u32 ), bad );
4188+
4189+ /* struct_v, struct_compat, and struct_len in MDSCapMatch */
4190+ ceph_decode_skip_n (& p , end , 2 + sizeof (u32 ), bad );
4191+ ceph_decode_64_safe (& p , end , cap_auths [i ].match .uid , bad );
4192+ ceph_decode_32_safe (& p , end , _len , bad );
4193+ if (_len ) {
4194+ cap_auths [i ].match .gids = kcalloc (_len , sizeof (u32 ),
4195+ GFP_KERNEL );
4196+ if (!cap_auths [i ].match .gids ) {
4197+ pr_err_client (cl , "No memory for gids\n" );
4198+ goto fail ;
4199+ }
4200+
4201+ cap_auths [i ].match .num_gids = _len ;
4202+ for (j = 0 ; j < _len ; j ++ )
4203+ ceph_decode_32_safe (& p , end ,
4204+ cap_auths [i ].match .gids [j ],
4205+ bad );
4206+ }
4207+
4208+ ceph_decode_32_safe (& p , end , _len , bad );
4209+ if (_len ) {
4210+ cap_auths [i ].match .path = kcalloc (_len + 1 , sizeof (char ),
4211+ GFP_KERNEL );
4212+ if (!cap_auths [i ].match .path ) {
4213+ pr_err_client (cl , "No memory for path\n" );
4214+ goto fail ;
4215+ }
4216+ ceph_decode_copy (& p , cap_auths [i ].match .path , _len );
4217+
4218+ /* Remove the tailing '/' */
4219+ while (_len && cap_auths [i ].match .path [_len - 1 ] == '/' ) {
4220+ cap_auths [i ].match .path [_len - 1 ] = '\0' ;
4221+ _len -= 1 ;
4222+ }
4223+ }
4224+
4225+ ceph_decode_32_safe (& p , end , _len , bad );
4226+ if (_len ) {
4227+ cap_auths [i ].match .fs_name = kcalloc (_len + 1 , sizeof (char ),
4228+ GFP_KERNEL );
4229+ if (!cap_auths [i ].match .fs_name ) {
4230+ pr_err_client (cl , "No memory for fs_name\n" );
4231+ goto fail ;
4232+ }
4233+ ceph_decode_copy (& p , cap_auths [i ].match .fs_name , _len );
4234+ }
4235+
4236+ ceph_decode_8_safe (& p , end , cap_auths [i ].match .root_squash , bad );
4237+ ceph_decode_8_safe (& p , end , cap_auths [i ].readable , bad );
4238+ ceph_decode_8_safe (& p , end , cap_auths [i ].writeable , bad );
4239+ doutc (cl , "uid %lld, num_gids %u, path %s, fs_name %s, root_squash %d, readable %d, writeable %d\n" ,
4240+ cap_auths [i ].match .uid , cap_auths [i ].match .num_gids ,
4241+ cap_auths [i ].match .path , cap_auths [i ].match .fs_name ,
4242+ cap_auths [i ].match .root_squash ,
4243+ cap_auths [i ].readable , cap_auths [i ].writeable );
4244+ }
4245+ }
4246+
4247+ skip_cap_auths :
41634248 mutex_lock (& mdsc -> mutex );
4249+ if (op == CEPH_SESSION_OPEN ) {
4250+ if (mdsc -> s_cap_auths ) {
4251+ for (i = 0 ; i < mdsc -> s_cap_auths_num ; i ++ ) {
4252+ kfree (mdsc -> s_cap_auths [i ].match .gids );
4253+ kfree (mdsc -> s_cap_auths [i ].match .path );
4254+ kfree (mdsc -> s_cap_auths [i ].match .fs_name );
4255+ }
4256+ kfree (mdsc -> s_cap_auths );
4257+ }
4258+ mdsc -> s_cap_auths_num = cap_auths_num ;
4259+ mdsc -> s_cap_auths = cap_auths ;
4260+ }
41644261 if (op == CEPH_SESSION_CLOSE ) {
41654262 ceph_get_mds_session (session );
41664263 __unregister_session (mdsc , session );
@@ -4290,6 +4387,13 @@ static void handle_session(struct ceph_mds_session *session,
42904387 pr_err_client (cl , "corrupt message mds%d len %d\n" , mds ,
42914388 (int )msg -> front .iov_len );
42924389 ceph_msg_dump (msg );
4390+ fail :
4391+ for (i = 0 ; i < cap_auths_num ; i ++ ) {
4392+ kfree (cap_auths [i ].match .gids );
4393+ kfree (cap_auths [i ].match .path );
4394+ kfree (cap_auths [i ].match .fs_name );
4395+ }
4396+ kfree (cap_auths );
42934397 return ;
42944398}
42954399
0 commit comments