@@ -4112,10 +4112,13 @@ static void handle_session(struct ceph_mds_session *session,
4112
4112
void * p = msg -> front .iov_base ;
4113
4113
void * end = p + msg -> front .iov_len ;
4114
4114
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 ;
4116
4117
u64 seq , features = 0 ;
4117
4118
int wake = 0 ;
4118
4119
bool blocklisted = false;
4120
+ u32 i ;
4121
+
4119
4122
4120
4123
/* decode */
4121
4124
ceph_decode_need (& p , end , sizeof (* h ), bad );
@@ -4160,7 +4163,101 @@ static void handle_session(struct ceph_mds_session *session,
4160
4163
}
4161
4164
}
4162
4165
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 :
4163
4248
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
+ }
4164
4261
if (op == CEPH_SESSION_CLOSE ) {
4165
4262
ceph_get_mds_session (session );
4166
4263
__unregister_session (mdsc , session );
@@ -4290,6 +4387,13 @@ static void handle_session(struct ceph_mds_session *session,
4290
4387
pr_err_client (cl , "corrupt message mds%d len %d\n" , mds ,
4291
4388
(int )msg -> front .iov_len );
4292
4389
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 );
4293
4397
return ;
4294
4398
}
4295
4399
0 commit comments