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

ceph: kstrdup() memory handling

Currently, there is no check for the kstrdup() for r_path2,
r_path1 and snapdir_name as various locations as there is a
possibility of failure during memory pressure. Therefore,
returning ENOMEM where the checks have been missed.

Signed-off-by: Sanidhya Kashyap <sanidhya.gatech@gmail.com>
Signed-off-by: Yan, Zheng <zyan@redhat.com>

authored by

Sanidhya Kashyap and committed by
Ilya Dryomov
a149bb9a c1d00b2d

+44 -13
+18 -6
fs/ceph/dir.c
··· 337 337 ceph_mdsc_put_request(req); 338 338 return err; 339 339 } 340 - req->r_inode = inode; 341 - ihold(inode); 342 - req->r_dentry = dget(file->f_path.dentry); 343 340 /* hints to request -> mds selection code */ 344 341 req->r_direct_mode = USE_AUTH_MDS; 345 342 req->r_direct_hash = ceph_frag_value(frag); 346 343 req->r_direct_is_hash = true; 347 - req->r_path2 = kstrdup(fi->last_name, GFP_NOFS); 344 + if (fi->last_name) { 345 + req->r_path2 = kstrdup(fi->last_name, GFP_NOFS); 346 + if (!req->r_path2) { 347 + ceph_mdsc_put_request(req); 348 + return -ENOMEM; 349 + } 350 + } 348 351 req->r_readdir_offset = fi->next_offset; 349 352 req->r_args.readdir.frag = cpu_to_le32(frag); 353 + 354 + req->r_inode = inode; 355 + ihold(inode); 356 + req->r_dentry = dget(file->f_path.dentry); 350 357 err = ceph_mdsc_do_request(mdsc, NULL, req); 351 358 if (err < 0) { 352 359 ceph_mdsc_put_request(req); ··· 764 757 err = PTR_ERR(req); 765 758 goto out; 766 759 } 760 + req->r_path2 = kstrdup(dest, GFP_NOFS); 761 + if (!req->r_path2) { 762 + err = -ENOMEM; 763 + ceph_mdsc_put_request(req); 764 + goto out; 765 + } 766 + req->r_locked_dir = dir; 767 767 req->r_dentry = dget(dentry); 768 768 req->r_num_caps = 2; 769 - req->r_path2 = kstrdup(dest, GFP_NOFS); 770 - req->r_locked_dir = dir; 771 769 req->r_dentry_drop = CEPH_CAP_FILE_SHARED; 772 770 req->r_dentry_unless = CEPH_CAP_FILE_EXCL; 773 771 err = ceph_mdsc_do_request(mdsc, dir, req);
+10
fs/ceph/super.c
··· 345 345 fsopt->rsize = CEPH_RSIZE_DEFAULT; 346 346 fsopt->rasize = CEPH_RASIZE_DEFAULT; 347 347 fsopt->snapdir_name = kstrdup(CEPH_SNAPDIRNAME_DEFAULT, GFP_KERNEL); 348 + if (!fsopt->snapdir_name) { 349 + err = -ENOMEM; 350 + goto out; 351 + } 352 + 348 353 fsopt->caps_wanted_delay_min = CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT; 349 354 fsopt->caps_wanted_delay_max = CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT; 350 355 fsopt->cap_release_safety = CEPH_CAP_RELEASE_SAFETY_DEFAULT; ··· 735 730 if (IS_ERR(req)) 736 731 return ERR_CAST(req); 737 732 req->r_path1 = kstrdup(path, GFP_NOFS); 733 + if (!req->r_path1) { 734 + root = ERR_PTR(-ENOMEM); 735 + goto out; 736 + } 737 + 738 738 req->r_ino1.ino = CEPH_INO_ROOT; 739 739 req->r_ino1.snap = CEPH_NOSNAP; 740 740 req->r_started = started;
+16 -7
fs/ceph/xattr.c
··· 877 877 err = PTR_ERR(req); 878 878 goto out; 879 879 } 880 - req->r_inode = inode; 881 - ihold(inode); 882 - req->r_inode_drop = CEPH_CAP_XATTR_SHARED; 883 - req->r_num_caps = 1; 880 + 884 881 req->r_args.setxattr.flags = cpu_to_le32(flags); 885 882 req->r_path2 = kstrdup(name, GFP_NOFS); 883 + if (!req->r_path2) { 884 + ceph_mdsc_put_request(req); 885 + err = -ENOMEM; 886 + goto out; 887 + } 886 888 887 889 req->r_pagelist = pagelist; 888 890 pagelist = NULL; 891 + 892 + req->r_inode = inode; 893 + ihold(inode); 894 + req->r_num_caps = 1; 895 + req->r_inode_drop = CEPH_CAP_XATTR_SHARED; 889 896 890 897 dout("xattr.ver (before): %lld\n", ci->i_xattrs.version); 891 898 err = ceph_mdsc_do_request(mdsc, NULL, req); ··· 1026 1019 USE_AUTH_MDS); 1027 1020 if (IS_ERR(req)) 1028 1021 return PTR_ERR(req); 1022 + req->r_path2 = kstrdup(name, GFP_NOFS); 1023 + if (!req->r_path2) 1024 + return -ENOMEM; 1025 + 1029 1026 req->r_inode = inode; 1030 1027 ihold(inode); 1031 - req->r_inode_drop = CEPH_CAP_XATTR_SHARED; 1032 1028 req->r_num_caps = 1; 1033 - req->r_path2 = kstrdup(name, GFP_NOFS); 1034 - 1029 + req->r_inode_drop = CEPH_CAP_XATTR_SHARED; 1035 1030 err = ceph_mdsc_do_request(mdsc, NULL, req); 1036 1031 ceph_mdsc_put_request(req); 1037 1032 return err;