Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'pull-ceph-d_name-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull ceph dentry->d_name fixes from Al Viro:
"Stuff that had fallen through the cracks back in February; ceph folks
tested that pile and said they prefer to have it go through my tree..."

* tag 'pull-ceph-d_name-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
ceph: fix a race with rename() in ceph_mdsc_build_path()
prep for ceph_encode_encrypted_fname() fixes
[ceph] parse_longname(): strrchr() expects NUL-terminated string

+43 -86
+7 -11
fs/ceph/caps.c
··· 4957 4957 cl = ceph_inode_to_client(dir); 4958 4958 spin_lock(&dentry->d_lock); 4959 4959 if (ret && di->lease_session && di->lease_session->s_mds == mds) { 4960 + int len = dentry->d_name.len; 4960 4961 doutc(cl, "%p mds%d seq %d\n", dentry, mds, 4961 4962 (int)di->lease_seq); 4962 4963 rel->dname_seq = cpu_to_le32(di->lease_seq); 4963 4964 __ceph_mdsc_drop_dentry_lease(dentry); 4965 + memcpy(*p, dentry->d_name.name, len); 4964 4966 spin_unlock(&dentry->d_lock); 4965 4967 if (IS_ENCRYPTED(dir) && fscrypt_has_encryption_key(dir)) { 4966 - int ret2 = ceph_encode_encrypted_fname(dir, dentry, *p); 4967 - 4968 - if (ret2 < 0) 4969 - return ret2; 4970 - 4971 - rel->dname_len = cpu_to_le32(ret2); 4972 - *p += ret2; 4973 - } else { 4974 - rel->dname_len = cpu_to_le32(dentry->d_name.len); 4975 - memcpy(*p, dentry->d_name.name, dentry->d_name.len); 4976 - *p += dentry->d_name.len; 4968 + len = ceph_encode_encrypted_dname(dir, *p, len); 4969 + if (len < 0) 4970 + return len; 4977 4971 } 4972 + rel->dname_len = cpu_to_le32(len); 4973 + *p += len; 4978 4974 } else { 4979 4975 spin_unlock(&dentry->d_lock); 4980 4976 }
+27 -55
fs/ceph/crypto.c
··· 215 215 struct ceph_client *cl = ceph_inode_to_client(parent); 216 216 struct inode *dir = NULL; 217 217 struct ceph_vino vino = { .snap = CEPH_NOSNAP }; 218 - char *inode_number; 219 - char *name_end; 220 - int orig_len = *name_len; 218 + char *name_end, *inode_number; 221 219 int ret = -EIO; 222 - 220 + /* NUL-terminate */ 221 + char *str __free(kfree) = kmemdup_nul(name, *name_len, GFP_KERNEL); 222 + if (!str) 223 + return ERR_PTR(-ENOMEM); 223 224 /* Skip initial '_' */ 224 - name++; 225 - name_end = strrchr(name, '_'); 225 + str++; 226 + name_end = strrchr(str, '_'); 226 227 if (!name_end) { 227 - doutc(cl, "failed to parse long snapshot name: %s\n", name); 228 + doutc(cl, "failed to parse long snapshot name: %s\n", str); 228 229 return ERR_PTR(-EIO); 229 230 } 230 - *name_len = (name_end - name); 231 + *name_len = (name_end - str); 231 232 if (*name_len <= 0) { 232 233 pr_err_client(cl, "failed to parse long snapshot name\n"); 233 234 return ERR_PTR(-EIO); 234 235 } 235 236 236 237 /* Get the inode number */ 237 - inode_number = kmemdup_nul(name_end + 1, 238 - orig_len - *name_len - 2, 239 - GFP_KERNEL); 240 - if (!inode_number) 241 - return ERR_PTR(-ENOMEM); 238 + inode_number = name_end + 1; 242 239 ret = kstrtou64(inode_number, 10, &vino.ino); 243 240 if (ret) { 244 - doutc(cl, "failed to parse inode number: %s\n", name); 245 - dir = ERR_PTR(ret); 246 - goto out; 241 + doutc(cl, "failed to parse inode number: %s\n", str); 242 + return ERR_PTR(ret); 247 243 } 248 244 249 245 /* And finally the inode */ ··· 250 254 if (IS_ERR(dir)) 251 255 doutc(cl, "can't find inode %s (%s)\n", inode_number, name); 252 256 } 253 - 254 - out: 255 - kfree(inode_number); 256 257 return dir; 257 258 } 258 259 259 - int ceph_encode_encrypted_dname(struct inode *parent, struct qstr *d_name, 260 - char *buf) 260 + int ceph_encode_encrypted_dname(struct inode *parent, char *buf, int elen) 261 261 { 262 262 struct ceph_client *cl = ceph_inode_to_client(parent); 263 263 struct inode *dir = parent; 264 - struct qstr iname; 264 + char *p = buf; 265 265 u32 len; 266 - int name_len; 267 - int elen; 266 + int name_len = elen; 268 267 int ret; 269 268 u8 *cryptbuf = NULL; 270 269 271 - iname.name = d_name->name; 272 - name_len = d_name->len; 273 - 274 270 /* Handle the special case of snapshot names that start with '_' */ 275 - if ((ceph_snap(dir) == CEPH_SNAPDIR) && (name_len > 0) && 276 - (iname.name[0] == '_')) { 277 - dir = parse_longname(parent, iname.name, &name_len); 271 + if (ceph_snap(dir) == CEPH_SNAPDIR && *p == '_') { 272 + dir = parse_longname(parent, p, &name_len); 278 273 if (IS_ERR(dir)) 279 274 return PTR_ERR(dir); 280 - iname.name++; /* skip initial '_' */ 275 + p++; /* skip initial '_' */ 281 276 } 282 - iname.len = name_len; 283 277 284 - if (!fscrypt_has_encryption_key(dir)) { 285 - memcpy(buf, d_name->name, d_name->len); 286 - elen = d_name->len; 278 + if (!fscrypt_has_encryption_key(dir)) 287 279 goto out; 288 - } 289 280 290 281 /* 291 282 * Convert cleartext d_name to ciphertext. If result is longer than ··· 280 297 * 281 298 * See: fscrypt_setup_filename 282 299 */ 283 - if (!fscrypt_fname_encrypted_size(dir, iname.len, NAME_MAX, &len)) { 300 + if (!fscrypt_fname_encrypted_size(dir, name_len, NAME_MAX, &len)) { 284 301 elen = -ENAMETOOLONG; 285 302 goto out; 286 303 } ··· 293 310 goto out; 294 311 } 295 312 296 - ret = fscrypt_fname_encrypt(dir, &iname, cryptbuf, len); 313 + ret = fscrypt_fname_encrypt(dir, 314 + &(struct qstr)QSTR_INIT(p, name_len), 315 + cryptbuf, len); 297 316 if (ret) { 298 317 elen = ret; 299 318 goto out; ··· 316 331 } 317 332 318 333 /* base64 encode the encrypted name */ 319 - elen = ceph_base64_encode(cryptbuf, len, buf); 320 - doutc(cl, "base64-encoded ciphertext name = %.*s\n", elen, buf); 334 + elen = ceph_base64_encode(cryptbuf, len, p); 335 + doutc(cl, "base64-encoded ciphertext name = %.*s\n", elen, p); 321 336 322 337 /* To understand the 240 limit, see CEPH_NOHASH_NAME_MAX comments */ 323 338 WARN_ON(elen > 240); 324 - if ((elen > 0) && (dir != parent)) { 325 - char tmp_buf[NAME_MAX]; 326 - 327 - elen = snprintf(tmp_buf, sizeof(tmp_buf), "_%.*s_%ld", 328 - elen, buf, dir->i_ino); 329 - memcpy(buf, tmp_buf, elen); 330 - } 339 + if (dir != parent) // leading _ is already there; append _<inum> 340 + elen += 1 + sprintf(p + elen, "_%ld", dir->i_ino); 331 341 332 342 out: 333 343 kfree(cryptbuf); ··· 333 353 iput(dir); 334 354 } 335 355 return elen; 336 - } 337 - 338 - int ceph_encode_encrypted_fname(struct inode *parent, struct dentry *dentry, 339 - char *buf) 340 - { 341 - WARN_ON_ONCE(!fscrypt_has_encryption_key(parent)); 342 - 343 - return ceph_encode_encrypted_dname(parent, &dentry->d_name, buf); 344 356 } 345 357 346 358 /**
+4 -14
fs/ceph/crypto.h
··· 102 102 struct ceph_acl_sec_ctx *as); 103 103 void ceph_fscrypt_as_ctx_to_req(struct ceph_mds_request *req, 104 104 struct ceph_acl_sec_ctx *as); 105 - int ceph_encode_encrypted_dname(struct inode *parent, struct qstr *d_name, 106 - char *buf); 107 - int ceph_encode_encrypted_fname(struct inode *parent, struct dentry *dentry, 108 - char *buf); 105 + int ceph_encode_encrypted_dname(struct inode *parent, char *buf, int len); 109 106 110 107 static inline int ceph_fname_alloc_buffer(struct inode *parent, 111 108 struct fscrypt_str *fname) ··· 191 194 { 192 195 } 193 196 194 - static inline int ceph_encode_encrypted_dname(struct inode *parent, 195 - struct qstr *d_name, char *buf) 197 + static inline int ceph_encode_encrypted_dname(struct inode *parent, char *buf, 198 + int len) 196 199 { 197 - memcpy(buf, d_name->name, d_name->len); 198 - return d_name->len; 199 - } 200 - 201 - static inline int ceph_encode_encrypted_fname(struct inode *parent, 202 - struct dentry *dentry, char *buf) 203 - { 204 - return -EOPNOTSUPP; 200 + return len; 205 201 } 206 202 207 203 static inline int ceph_fname_alloc_buffer(struct inode *parent,
+3 -4
fs/ceph/dir.c
··· 423 423 req->r_inode_drop = CEPH_CAP_FILE_EXCL; 424 424 } 425 425 if (dfi->last_name) { 426 - struct qstr d_name = { .name = dfi->last_name, 427 - .len = strlen(dfi->last_name) }; 426 + int len = strlen(dfi->last_name); 428 427 429 428 req->r_path2 = kzalloc(NAME_MAX + 1, GFP_KERNEL); 430 429 if (!req->r_path2) { 431 430 ceph_mdsc_put_request(req); 432 431 return -ENOMEM; 433 432 } 433 + memcpy(req->r_path2, dfi->last_name, len); 434 434 435 - err = ceph_encode_encrypted_dname(inode, &d_name, 436 - req->r_path2); 435 + err = ceph_encode_encrypted_dname(inode, req->r_path2, len); 437 436 if (err < 0) { 438 437 ceph_mdsc_put_request(req); 439 438 return err;
+2 -2
fs/ceph/mds_client.c
··· 2766 2766 } 2767 2767 2768 2768 if (fscrypt_has_encryption_key(d_inode(parent))) { 2769 - len = ceph_encode_encrypted_fname(d_inode(parent), 2770 - cur, buf); 2769 + len = ceph_encode_encrypted_dname(d_inode(parent), 2770 + buf, len); 2771 2771 if (len < 0) { 2772 2772 dput(parent); 2773 2773 dput(cur);