Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: cifs: fix parsing of hostname in dfs referrals cifs: display fsc in /proc/mounts cifs: enable fscache iff fsc mount option is used explicitly cifs: allow fsc mount option only if CONFIG_CIFS_FSCACHE is set cifs: Handle extended attribute name cifs_acl to generate cifs acl blob (try #4) cifs: Misc. cleanup in cifsacl handling [try #4] cifs: trivial comment fix for cifs_invalidate_mapping [CIFS] fs/cifs/Kconfig: CIFS depends on CRYPTO_HMAC cifs: don't take extra tlink reference in initiate_cifs_search cifs: Percolate error up to the caller during get/set acls [try #4] cifs: fix another memleak, in cifs_root_iget cifs: fix potential use-after-free in cifs_oplock_break_put
This commit is contained in:
commit
8520eeaa12
|
@ -4,6 +4,7 @@ config CIFS
|
||||||
select NLS
|
select NLS
|
||||||
select CRYPTO
|
select CRYPTO
|
||||||
select CRYPTO_MD5
|
select CRYPTO_MD5
|
||||||
|
select CRYPTO_HMAC
|
||||||
select CRYPTO_ARC4
|
select CRYPTO_ARC4
|
||||||
help
|
help
|
||||||
This is the client VFS module for the Common Internet File System
|
This is the client VFS module for the Common Internet File System
|
||||||
|
@ -143,6 +144,13 @@ config CIFS_FSCACHE
|
||||||
to be cached locally on disk through the general filesystem cache
|
to be cached locally on disk through the general filesystem cache
|
||||||
manager. If unsure, say N.
|
manager. If unsure, say N.
|
||||||
|
|
||||||
|
config CIFS_ACL
|
||||||
|
bool "Provide CIFS ACL support (EXPERIMENTAL)"
|
||||||
|
depends on EXPERIMENTAL && CIFS_XATTR
|
||||||
|
help
|
||||||
|
Allows to fetch CIFS/NTFS ACL from the server. The DACL blob
|
||||||
|
is handed over to the application/caller.
|
||||||
|
|
||||||
config CIFS_EXPERIMENTAL
|
config CIFS_EXPERIMENTAL
|
||||||
bool "CIFS Experimental Features (EXPERIMENTAL)"
|
bool "CIFS Experimental Features (EXPERIMENTAL)"
|
||||||
depends on CIFS && EXPERIMENTAL
|
depends on CIFS && EXPERIMENTAL
|
||||||
|
|
|
@ -560,7 +560,7 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
|
||||||
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
||||||
|
|
||||||
if (IS_ERR(tlink))
|
if (IS_ERR(tlink))
|
||||||
return NULL;
|
return ERR_CAST(tlink);
|
||||||
|
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
|
rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
|
||||||
|
@ -568,7 +568,9 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
|
||||||
|
|
||||||
cifs_put_tlink(tlink);
|
cifs_put_tlink(tlink);
|
||||||
|
|
||||||
cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen);
|
cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
|
||||||
|
if (rc)
|
||||||
|
return ERR_PTR(rc);
|
||||||
return pntsd;
|
return pntsd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,7 +585,7 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
|
||||||
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
||||||
|
|
||||||
if (IS_ERR(tlink))
|
if (IS_ERR(tlink))
|
||||||
return NULL;
|
return ERR_CAST(tlink);
|
||||||
|
|
||||||
tcon = tlink_tcon(tlink);
|
tcon = tlink_tcon(tlink);
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
|
@ -591,23 +593,22 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
|
||||||
rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0,
|
rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0,
|
||||||
&fid, &oplock, NULL, cifs_sb->local_nls,
|
&fid, &oplock, NULL, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if (rc) {
|
if (!rc) {
|
||||||
cERROR(1, "Unable to open file to get ACL");
|
rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
|
||||||
goto out;
|
CIFSSMBClose(xid, tcon, fid);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
|
|
||||||
cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen);
|
|
||||||
|
|
||||||
CIFSSMBClose(xid, tcon, fid);
|
|
||||||
out:
|
|
||||||
cifs_put_tlink(tlink);
|
cifs_put_tlink(tlink);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
|
|
||||||
|
cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
|
||||||
|
if (rc)
|
||||||
|
return ERR_PTR(rc);
|
||||||
return pntsd;
|
return pntsd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve an ACL from the server */
|
/* Retrieve an ACL from the server */
|
||||||
static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
|
struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
|
||||||
struct inode *inode, const char *path,
|
struct inode *inode, const char *path,
|
||||||
u32 *pacllen)
|
u32 *pacllen)
|
||||||
{
|
{
|
||||||
|
@ -695,7 +696,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
|
/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
|
||||||
void
|
int
|
||||||
cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
|
cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
|
||||||
struct inode *inode, const char *path, const __u16 *pfid)
|
struct inode *inode, const char *path, const __u16 *pfid)
|
||||||
{
|
{
|
||||||
|
@ -711,17 +712,21 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
|
||||||
pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
|
pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
|
||||||
|
|
||||||
/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
|
/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
|
||||||
if (pntsd)
|
if (IS_ERR(pntsd)) {
|
||||||
|
rc = PTR_ERR(pntsd);
|
||||||
|
cERROR(1, "%s: error %d getting sec desc", __func__, rc);
|
||||||
|
} else {
|
||||||
rc = parse_sec_desc(pntsd, acllen, fattr);
|
rc = parse_sec_desc(pntsd, acllen, fattr);
|
||||||
if (rc)
|
|
||||||
cFYI(1, "parse sec desc failed rc = %d", rc);
|
|
||||||
|
|
||||||
kfree(pntsd);
|
kfree(pntsd);
|
||||||
return;
|
if (rc)
|
||||||
|
cERROR(1, "parse sec desc failed rc = %d", rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert mode bits to an ACL so we can update the ACL on the server */
|
/* Convert mode bits to an ACL so we can update the ACL on the server */
|
||||||
int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
|
int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
__u32 secdesclen = 0;
|
__u32 secdesclen = 0;
|
||||||
|
@ -736,7 +741,10 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
|
||||||
/* Add three ACEs for owner, group, everyone getting rid of
|
/* Add three ACEs for owner, group, everyone getting rid of
|
||||||
other ACEs as chmod disables ACEs and set the security descriptor */
|
other ACEs as chmod disables ACEs and set the security descriptor */
|
||||||
|
|
||||||
if (pntsd) {
|
if (IS_ERR(pntsd)) {
|
||||||
|
rc = PTR_ERR(pntsd);
|
||||||
|
cERROR(1, "%s: error %d getting sec desc", __func__, rc);
|
||||||
|
} else {
|
||||||
/* allocate memory for the smb header,
|
/* allocate memory for the smb header,
|
||||||
set security descriptor request security descriptor
|
set security descriptor request security descriptor
|
||||||
parameters, and secuirty descriptor itself */
|
parameters, and secuirty descriptor itself */
|
||||||
|
|
|
@ -458,6 +458,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
|
||||||
seq_printf(s, ",acl");
|
seq_printf(s, ",acl");
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
|
||||||
seq_printf(s, ",mfsymlinks");
|
seq_printf(s, ",mfsymlinks");
|
||||||
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE)
|
||||||
|
seq_printf(s, ",fsc");
|
||||||
|
|
||||||
seq_printf(s, ",rsize=%d", cifs_sb->rsize);
|
seq_printf(s, ",rsize=%d", cifs_sb->rsize);
|
||||||
seq_printf(s, ",wsize=%d", cifs_sb->wsize);
|
seq_printf(s, ",wsize=%d", cifs_sb->wsize);
|
||||||
|
|
|
@ -130,10 +130,12 @@ extern int cifs_get_file_info_unix(struct file *filp);
|
||||||
extern int cifs_get_inode_info_unix(struct inode **pinode,
|
extern int cifs_get_inode_info_unix(struct inode **pinode,
|
||||||
const unsigned char *search_path,
|
const unsigned char *search_path,
|
||||||
struct super_block *sb, int xid);
|
struct super_block *sb, int xid);
|
||||||
extern void cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
|
extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
|
||||||
struct cifs_fattr *fattr, struct inode *inode,
|
struct cifs_fattr *fattr, struct inode *inode,
|
||||||
const char *path, const __u16 *pfid);
|
const char *path, const __u16 *pfid);
|
||||||
extern int mode_to_acl(struct inode *inode, const char *path, __u64);
|
extern int mode_to_cifs_acl(struct inode *inode, const char *path, __u64);
|
||||||
|
extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
|
||||||
|
const char *, u32 *);
|
||||||
|
|
||||||
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
|
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
|
||||||
const char *);
|
const char *);
|
||||||
|
|
|
@ -1352,6 +1352,11 @@ cifs_parse_mount_options(char *options, const char *devname,
|
||||||
"supported. Instead set "
|
"supported. Instead set "
|
||||||
"/proc/fs/cifs/LookupCacheEnabled to 0\n");
|
"/proc/fs/cifs/LookupCacheEnabled to 0\n");
|
||||||
} else if (strnicmp(data, "fsc", 3) == 0) {
|
} else if (strnicmp(data, "fsc", 3) == 0) {
|
||||||
|
#ifndef CONFIG_CIFS_FSCACHE
|
||||||
|
cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE"
|
||||||
|
"kernel config option set");
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
vol->fsc = true;
|
vol->fsc = true;
|
||||||
} else if (strnicmp(data, "mfsymlinks", 10) == 0) {
|
} else if (strnicmp(data, "mfsymlinks", 10) == 0) {
|
||||||
vol->mfsymlinks = true;
|
vol->mfsymlinks = true;
|
||||||
|
|
|
@ -66,7 +66,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
|
||||||
/* Search for server name delimiter */
|
/* Search for server name delimiter */
|
||||||
sep = memchr(hostname, '\\', len);
|
sep = memchr(hostname, '\\', len);
|
||||||
if (sep)
|
if (sep)
|
||||||
len = sep - unc;
|
len = sep - hostname;
|
||||||
else
|
else
|
||||||
cFYI(1, "%s: probably server name is whole unc: %s",
|
cFYI(1, "%s: probably server name is whole unc: %s",
|
||||||
__func__, unc);
|
__func__, unc);
|
||||||
|
|
|
@ -2271,8 +2271,10 @@ void cifs_oplock_break_get(struct cifsFileInfo *cfile)
|
||||||
|
|
||||||
void cifs_oplock_break_put(struct cifsFileInfo *cfile)
|
void cifs_oplock_break_put(struct cifsFileInfo *cfile)
|
||||||
{
|
{
|
||||||
|
struct super_block *sb = cfile->dentry->d_sb;
|
||||||
|
|
||||||
cifsFileInfo_put(cfile);
|
cifsFileInfo_put(cfile);
|
||||||
cifs_sb_deactive(cfile->dentry->d_sb);
|
cifs_sb_deactive(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct address_space_operations cifs_addr_ops = {
|
const struct address_space_operations cifs_addr_ops = {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* fs/cifs/fscache.c - CIFS filesystem cache interface
|
* fs/cifs/fscache.c - CIFS filesystem cache interface
|
||||||
*
|
*
|
||||||
* Copyright (c) 2010 Novell, Inc.
|
* Copyright (c) 2010 Novell, Inc.
|
||||||
* Author(s): Suresh Jayaraman (sjayaraman@suse.de>
|
* Author(s): Suresh Jayaraman <sjayaraman@suse.de>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as published
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
|
@ -67,11 +67,13 @@ static void cifs_fscache_enable_inode_cookie(struct inode *inode)
|
||||||
if (cifsi->fscache)
|
if (cifsi->fscache)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) {
|
||||||
cifsi->fscache = fscache_acquire_cookie(tcon->fscache,
|
cifsi->fscache = fscache_acquire_cookie(tcon->fscache,
|
||||||
&cifs_fscache_inode_object_def, cifsi);
|
&cifs_fscache_inode_object_def, cifsi);
|
||||||
cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache,
|
cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache,
|
||||||
cifsi->fscache);
|
cifsi->fscache);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void cifs_fscache_release_inode_cookie(struct inode *inode)
|
void cifs_fscache_release_inode_cookie(struct inode *inode)
|
||||||
{
|
{
|
||||||
|
@ -101,10 +103,8 @@ void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
|
||||||
{
|
{
|
||||||
if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
|
if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
|
||||||
cifs_fscache_disable_inode_cookie(inode);
|
cifs_fscache_disable_inode_cookie(inode);
|
||||||
else {
|
else
|
||||||
cifs_fscache_enable_inode_cookie(inode);
|
cifs_fscache_enable_inode_cookie(inode);
|
||||||
cFYI(1, "CIFS: fscache inode cookie set");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cifs_fscache_reset_inode_cookie(struct inode *inode)
|
void cifs_fscache_reset_inode_cookie(struct inode *inode)
|
||||||
|
|
|
@ -689,8 +689,13 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||||
/* fill in 0777 bits from ACL */
|
/* fill in 0777 bits from ACL */
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
|
||||||
cFYI(1, "Getting mode bits from ACL");
|
rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path,
|
||||||
cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid);
|
pfid);
|
||||||
|
if (rc) {
|
||||||
|
cFYI(1, "%s: Getting ACL failed with error: %d",
|
||||||
|
__func__, rc);
|
||||||
|
goto cgii_exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -881,8 +886,10 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
|
||||||
rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
|
rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
|
||||||
xid, NULL);
|
xid, NULL);
|
||||||
|
|
||||||
if (!inode)
|
if (!inode) {
|
||||||
return ERR_PTR(rc);
|
inode = ERR_PTR(rc);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_FSCACHE
|
#ifdef CONFIG_CIFS_FSCACHE
|
||||||
/* populate tcon->resource_id */
|
/* populate tcon->resource_id */
|
||||||
|
@ -898,13 +905,11 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
|
||||||
inode->i_uid = cifs_sb->mnt_uid;
|
inode->i_uid = cifs_sb->mnt_uid;
|
||||||
inode->i_gid = cifs_sb->mnt_gid;
|
inode->i_gid = cifs_sb->mnt_gid;
|
||||||
} else if (rc) {
|
} else if (rc) {
|
||||||
kfree(full_path);
|
|
||||||
_FreeXid(xid);
|
|
||||||
iget_failed(inode);
|
iget_failed(inode);
|
||||||
return ERR_PTR(rc);
|
inode = ERR_PTR(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
kfree(full_path);
|
kfree(full_path);
|
||||||
/* can not call macro FreeXid here since in a void func
|
/* can not call macro FreeXid here since in a void func
|
||||||
* TODO: This is no longer true
|
* TODO: This is no longer true
|
||||||
|
@ -1670,7 +1675,9 @@ cifs_inode_needs_reval(struct inode *inode)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check invalid_mapping flag and zap the cache if it's set */
|
/*
|
||||||
|
* Zap the cache. Called when invalid_mapping flag is set.
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
cifs_invalidate_mapping(struct inode *inode)
|
cifs_invalidate_mapping(struct inode *inode)
|
||||||
{
|
{
|
||||||
|
@ -2115,9 +2122,14 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
||||||
if (attrs->ia_valid & ATTR_MODE) {
|
if (attrs->ia_valid & ATTR_MODE) {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
|
||||||
rc = mode_to_acl(inode, full_path, mode);
|
rc = mode_to_cifs_acl(inode, full_path, mode);
|
||||||
else
|
if (rc) {
|
||||||
|
cFYI(1, "%s: Setting ACL failed with error: %d",
|
||||||
|
__func__, rc);
|
||||||
|
goto cifs_setattr_exit;
|
||||||
|
}
|
||||||
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (((mode & S_IWUGO) == 0) &&
|
if (((mode & S_IWUGO) == 0) &&
|
||||||
(cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
|
(cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
|
||||||
|
|
|
@ -226,26 +226,29 @@ static int initiate_cifs_search(const int xid, struct file *file)
|
||||||
char *full_path = NULL;
|
char *full_path = NULL;
|
||||||
struct cifsFileInfo *cifsFile;
|
struct cifsFileInfo *cifsFile;
|
||||||
struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
||||||
struct tcon_link *tlink;
|
struct tcon_link *tlink = NULL;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
|
|
||||||
|
if (file->private_data == NULL) {
|
||||||
tlink = cifs_sb_tlink(cifs_sb);
|
tlink = cifs_sb_tlink(cifs_sb);
|
||||||
if (IS_ERR(tlink))
|
if (IS_ERR(tlink))
|
||||||
return PTR_ERR(tlink);
|
return PTR_ERR(tlink);
|
||||||
pTcon = tlink_tcon(tlink);
|
|
||||||
|
|
||||||
if (file->private_data == NULL)
|
cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
|
||||||
file->private_data =
|
if (cifsFile == NULL) {
|
||||||
kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
|
|
||||||
if (file->private_data == NULL) {
|
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
}
|
}
|
||||||
|
file->private_data = cifsFile;
|
||||||
|
cifsFile->tlink = cifs_get_tlink(tlink);
|
||||||
|
pTcon = tlink_tcon(tlink);
|
||||||
|
} else {
|
||||||
cifsFile = file->private_data;
|
cifsFile = file->private_data;
|
||||||
|
pTcon = tlink_tcon(cifsFile->tlink);
|
||||||
|
}
|
||||||
|
|
||||||
cifsFile->invalidHandle = true;
|
cifsFile->invalidHandle = true;
|
||||||
cifsFile->srch_inf.endOfSearch = false;
|
cifsFile->srch_inf.endOfSearch = false;
|
||||||
cifsFile->tlink = cifs_get_tlink(tlink);
|
|
||||||
|
|
||||||
full_path = build_path_from_dentry(file->f_path.dentry);
|
full_path = build_path_from_dentry(file->f_path.dentry);
|
||||||
if (full_path == NULL) {
|
if (full_path == NULL) {
|
||||||
|
|
|
@ -30,10 +30,11 @@
|
||||||
|
|
||||||
#define MAX_EA_VALUE_SIZE 65535
|
#define MAX_EA_VALUE_SIZE 65535
|
||||||
#define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib"
|
#define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib"
|
||||||
|
#define CIFS_XATTR_CIFS_ACL "system.cifs_acl"
|
||||||
#define CIFS_XATTR_USER_PREFIX "user."
|
#define CIFS_XATTR_USER_PREFIX "user."
|
||||||
#define CIFS_XATTR_SYSTEM_PREFIX "system."
|
#define CIFS_XATTR_SYSTEM_PREFIX "system."
|
||||||
#define CIFS_XATTR_OS2_PREFIX "os2."
|
#define CIFS_XATTR_OS2_PREFIX "os2."
|
||||||
#define CIFS_XATTR_SECURITY_PREFIX ".security"
|
#define CIFS_XATTR_SECURITY_PREFIX "security."
|
||||||
#define CIFS_XATTR_TRUSTED_PREFIX "trusted."
|
#define CIFS_XATTR_TRUSTED_PREFIX "trusted."
|
||||||
#define XATTR_TRUSTED_PREFIX_LEN 8
|
#define XATTR_TRUSTED_PREFIX_LEN 8
|
||||||
#define XATTR_SECURITY_PREFIX_LEN 9
|
#define XATTR_SECURITY_PREFIX_LEN 9
|
||||||
|
@ -277,29 +278,8 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
|
||||||
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
|
|
||||||
__u16 fid;
|
|
||||||
int oplock = 0;
|
|
||||||
struct cifs_ntsd *pacl = NULL;
|
|
||||||
__u32 buflen = 0;
|
|
||||||
if (experimEnabled)
|
|
||||||
rc = CIFSSMBOpen(xid, pTcon, full_path,
|
|
||||||
FILE_OPEN, GENERIC_READ, 0, &fid,
|
|
||||||
&oplock, NULL, cifs_sb->local_nls,
|
|
||||||
cifs_sb->mnt_cifs_flags &
|
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
/* else rc is EOPNOTSUPP from above */
|
|
||||||
|
|
||||||
if (rc == 0) {
|
|
||||||
rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, &pacl,
|
|
||||||
&buflen);
|
|
||||||
CIFSSMBClose(xid, pTcon, fid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* EXPERIMENTAL */
|
|
||||||
#else
|
#else
|
||||||
cFYI(1, "query POSIX ACL not supported yet");
|
cFYI(1, "Query POSIX ACL not supported yet");
|
||||||
#endif /* CONFIG_CIFS_POSIX */
|
#endif /* CONFIG_CIFS_POSIX */
|
||||||
} else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
|
} else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
|
||||||
strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
|
strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
|
||||||
|
@ -311,8 +291,33 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
#else
|
#else
|
||||||
cFYI(1, "query POSIX default ACL not supported yet");
|
cFYI(1, "Query POSIX default ACL not supported yet");
|
||||||
#endif
|
#endif /* CONFIG_CIFS_POSIX */
|
||||||
|
} else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL,
|
||||||
|
strlen(CIFS_XATTR_CIFS_ACL)) == 0) {
|
||||||
|
#ifdef CONFIG_CIFS_ACL
|
||||||
|
u32 acllen;
|
||||||
|
struct cifs_ntsd *pacl;
|
||||||
|
|
||||||
|
pacl = get_cifs_acl(cifs_sb, direntry->d_inode,
|
||||||
|
full_path, &acllen);
|
||||||
|
if (IS_ERR(pacl)) {
|
||||||
|
rc = PTR_ERR(pacl);
|
||||||
|
cERROR(1, "%s: error %zd getting sec desc",
|
||||||
|
__func__, rc);
|
||||||
|
} else {
|
||||||
|
if (ea_value) {
|
||||||
|
if (acllen > buf_size)
|
||||||
|
acllen = -ERANGE;
|
||||||
|
else
|
||||||
|
memcpy(ea_value, pacl, acllen);
|
||||||
|
}
|
||||||
|
rc = acllen;
|
||||||
|
kfree(pacl);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
cFYI(1, "Query CIFS ACL not supported yet");
|
||||||
|
#endif /* CONFIG_CIFS_ACL */
|
||||||
} else if (strncmp(ea_name,
|
} else if (strncmp(ea_name,
|
||||||
CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) {
|
CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) {
|
||||||
cFYI(1, "Trusted xattr namespace not supported yet");
|
cFYI(1, "Trusted xattr namespace not supported yet");
|
||||||
|
|
Loading…
Reference in New Issue