Skip to content

Commit 8e8bb96

Browse files
committed
Merge git://git.samba.org/sfrench/cifs-2.6
Pull CIFS fixes from Steve French. * git://git.samba.org/sfrench/cifs-2.6: CIFS: Do not kmalloc under the flocks spinlock cifs: possible memory leak in xattr.
2 parents cd79453 + d575146 commit 8e8bb96

File tree

2 files changed

+59
-16
lines changed

2 files changed

+59
-16
lines changed

fs/cifs/file.c

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -920,16 +920,26 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
920920
for (lockp = &inode->i_flock; *lockp != NULL; \
921921
lockp = &(*lockp)->fl_next)
922922

923+
struct lock_to_push {
924+
struct list_head llist;
925+
__u64 offset;
926+
__u64 length;
927+
__u32 pid;
928+
__u16 netfid;
929+
__u8 type;
930+
};
931+
923932
static int
924933
cifs_push_posix_locks(struct cifsFileInfo *cfile)
925934
{
926935
struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
927936
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
928937
struct file_lock *flock, **before;
929-
struct cifsLockInfo *lck, *tmp;
938+
unsigned int count = 0, i = 0;
930939
int rc = 0, xid, type;
940+
struct list_head locks_to_send, *el;
941+
struct lock_to_push *lck, *tmp;
931942
__u64 length;
932-
struct list_head locks_to_send;
933943

934944
xid = GetXid();
935945

@@ -940,29 +950,55 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
940950
return rc;
941951
}
942952

953+
lock_flocks();
954+
cifs_for_each_lock(cfile->dentry->d_inode, before) {
955+
if ((*before)->fl_flags & FL_POSIX)
956+
count++;
957+
}
958+
unlock_flocks();
959+
943960
INIT_LIST_HEAD(&locks_to_send);
944961

962+
/*
963+
* Allocating count locks is enough because no locks can be added to
964+
* the list while we are holding cinode->lock_mutex that protects
965+
* locking operations of this inode.
966+
*/
967+
for (; i < count; i++) {
968+
lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL);
969+
if (!lck) {
970+
rc = -ENOMEM;
971+
goto err_out;
972+
}
973+
list_add_tail(&lck->llist, &locks_to_send);
974+
}
975+
976+
i = 0;
977+
el = locks_to_send.next;
945978
lock_flocks();
946979
cifs_for_each_lock(cfile->dentry->d_inode, before) {
980+
if (el == &locks_to_send) {
981+
/* something is really wrong */
982+
cERROR(1, "Can't push all brlocks!");
983+
break;
984+
}
947985
flock = *before;
986+
if ((flock->fl_flags & FL_POSIX) == 0)
987+
continue;
948988
length = 1 + flock->fl_end - flock->fl_start;
949989
if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK)
950990
type = CIFS_RDLCK;
951991
else
952992
type = CIFS_WRLCK;
953-
954-
lck = cifs_lock_init(flock->fl_start, length, type,
955-
cfile->netfid);
956-
if (!lck) {
957-
rc = -ENOMEM;
958-
goto send_locks;
959-
}
993+
lck = list_entry(el, struct lock_to_push, llist);
960994
lck->pid = flock->fl_pid;
961-
962-
list_add_tail(&lck->llist, &locks_to_send);
995+
lck->netfid = cfile->netfid;
996+
lck->length = length;
997+
lck->type = type;
998+
lck->offset = flock->fl_start;
999+
i++;
1000+
el = el->next;
9631001
}
964-
965-
send_locks:
9661002
unlock_flocks();
9671003

9681004
list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
@@ -979,11 +1015,18 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
9791015
kfree(lck);
9801016
}
9811017

1018+
out:
9821019
cinode->can_cache_brlcks = false;
9831020
mutex_unlock(&cinode->lock_mutex);
9841021

9851022
FreeXid(xid);
9861023
return rc;
1024+
err_out:
1025+
list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
1026+
list_del(&lck->llist);
1027+
kfree(lck);
1028+
}
1029+
goto out;
9871030
}
9881031

9891032
static int

fs/cifs/xattr.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
105105
struct cifs_tcon *pTcon;
106106
struct super_block *sb;
107107
char *full_path;
108-
struct cifs_ntsd *pacl;
109108

110109
if (direntry == NULL)
111110
return -EIO;
@@ -164,23 +163,24 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
164163
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
165164
} else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL,
166165
strlen(CIFS_XATTR_CIFS_ACL)) == 0) {
166+
#ifdef CONFIG_CIFS_ACL
167+
struct cifs_ntsd *pacl;
167168
pacl = kmalloc(value_size, GFP_KERNEL);
168169
if (!pacl) {
169170
cFYI(1, "%s: Can't allocate memory for ACL",
170171
__func__);
171172
rc = -ENOMEM;
172173
} else {
173-
#ifdef CONFIG_CIFS_ACL
174174
memcpy(pacl, ea_value, value_size);
175175
rc = set_cifs_acl(pacl, value_size,
176176
direntry->d_inode, full_path, CIFS_ACL_DACL);
177177
if (rc == 0) /* force revalidate of the inode */
178178
CIFS_I(direntry->d_inode)->time = 0;
179179
kfree(pacl);
180+
}
180181
#else
181182
cFYI(1, "Set CIFS ACL not supported yet");
182183
#endif /* CONFIG_CIFS_ACL */
183-
}
184184
} else {
185185
int temp;
186186
temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,

0 commit comments

Comments
 (0)