Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ddbb8684 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  cifs: remove never-used in6_addr option
  cifs: add addr= mount option alias for ip=
  [CIFS] Add mention of new mount parm (forceuid) to cifs readme
  cifs: make overriding of ownership conditional on new mount options
  cifs: fix IPv6 address length check
  cifs: clean up set_cifs_acl interfaces
  cifs: reorganize get_cifs_acl
  [CIFS] Update readme to indicate change to default mount (serverino)
  cifs: make serverino the default when mounting
  cifs: rename cifs_iget to cifs_root_iget
  cifs: make cnvrtDosUnixTm take a little-endian args and an offset
  cifs: have cifs_NTtimeToUnix take a little-endian arg
  cifs: tighten up default file_mode/dir_mode
  cifs: fix artificial limit on reading symlinks
parents 3296ca27 61b6bc52
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
Version 1.59
------------
Client uses server inode numbers (which are persistent) rather than
client generated ones by default (mount option "serverino" turned
on by default if server supports it).  Add forceuid and forcegid
mount options (so that when negotiating unix extensions specifying
which uid mounted does not immediately force the server's reported
uids to be overridden).

Version 1.58
------------
Guard against buffer overruns in various UCS-2 to UTF-8 string conversions
@@ -10,6 +19,8 @@ we converted from). Fix endianness of the vcnum field used during
session setup to distinguish multiple mounts to same server from different
userids. Raw NTLMSSP fixed (it requires /proc/fs/cifs/experimental
flag to be set to 2, and mount must enable krb5 to turn on extended security).
Performance of file create to Samba improved (posix create on lookup
removes 1 of 2 network requests sent on file create)
 
Version 1.57
------------
+14 −2
Original line number Diff line number Diff line
@@ -262,7 +262,8 @@ A partial list of the supported mount options follows:
		mount.	
  domain	Set the SMB/CIFS workgroup name prepended to the
		username during CIFS session establishment
  uid		Set the default uid for inodes. For mounts to servers
  forceuid	Set the default uid for inodes based on the uid
		passed in. For mounts to servers
		which do support the CIFS Unix extensions, such as a
		properly configured Samba server, the server provides
		the uid, gid and mode so this parameter should  not be
@@ -292,6 +293,12 @@ A partial list of the supported mount options follows:
		the client.  Note that the mount.cifs helper must be
		at version 1.10 or higher to support specifying the uid
		(or gid) in non-numeric form.
  forcegid	(similar to above but for the groupid instead of uid)
  uid		Set the default uid for inodes, and indicate to the
		cifs kernel driver which local user mounted . If the server
		supports the unix extensions the default uid is
		not used to fill in the owner fields of inodes (files)
		unless the "forceuid" parameter is specified.
  gid		Set the default gid for inodes (similar to above).
  file_mode     If CIFS Unix extensions are not supported by the server
		this overrides the default mode for file inodes.
@@ -388,8 +395,13 @@ A partial list of the supported mount options follows:
		or the CIFS Unix Extensions equivalent and for those
		this mount option will have no effect.  Exporting cifs mounts
		under nfsd requires this mount option on the cifs mount.
		This is now the default if server supports the 
		required network operation.
  noserverino   Client generates inode numbers (rather than using the actual one
		from the server) by default.
		from the server). These inode numbers will vary after
		unmount or reboot which can confuse some applications,
		but not all server filesystems support unique inode
		numbers.
  setuids       If the CIFS Unix extensions are negotiated with the server
		the client will attempt to set the effective uid and gid of
		the local process on newly created files, directories, and
+2 −4
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <linux/string.h>
#include <keys/user-type.h>
#include <linux/key-type.h>
#include <linux/inet.h>
#include "cifsglob.h"
#include "cifs_spnego.h"
#include "cifs_debug.h"
@@ -73,9 +74,6 @@ struct key_type cifs_spnego_key_type = {
 * strlen(";sec=ntlmsspi") */
#define MAX_MECH_STR_LEN	13

/* max possible addr len eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/128 */
#define MAX_IPV6_ADDR_LEN	43

/* strlen of "host=" */
#define HOST_KEY_LEN		5

@@ -102,7 +100,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
	   host=hostname sec=mechanism uid=0xFF user=username */
	desc_len = MAX_VER_STR_LEN +
		   HOST_KEY_LEN + strlen(hostname) +
		   IP_KEY_LEN + MAX_IPV6_ADDR_LEN +
		   IP_KEY_LEN + INET6_ADDRSTRLEN +
		   MAX_MECH_STR_LEN +
		   UID_KEY_LEN + (sizeof(uid_t) * 2) +
		   USER_KEY_LEN + strlen(sesInfo->userName) + 1;
+93 −85
Original line number Diff line number Diff line
@@ -552,130 +552,138 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
	return rc;
}


/* Retrieve an ACL from the server */
static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
				       const char *path, const __u16 *pfid)
static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
		__u16 fid, u32 *pacllen)
{
	struct cifsFileInfo *open_file = NULL;
	bool unlock_file = false;
	int xid;
	int rc = -EIO;
	__u16 fid;
	struct super_block *sb;
	struct cifs_sb_info *cifs_sb;
	struct cifs_ntsd *pntsd = NULL;

	cFYI(1, ("get mode from ACL for %s", path));

	if (inode == NULL)
		return NULL;
	int xid, rc;

	xid = GetXid();
	if (pfid == NULL)
		open_file = find_readable_file(CIFS_I(inode));
	else
		fid = *pfid;

	sb = inode->i_sb;
	if (sb == NULL) {
	rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
	FreeXid(xid);
		return NULL;


	cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
	return pntsd;
}
	cifs_sb = CIFS_SB(sb);

	if (open_file) {
		unlock_file = true;
		fid = open_file->netfid;
	} else if (pfid == NULL) {
static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
		const char *path, u32 *pacllen)
{
	struct cifs_ntsd *pntsd = NULL;
	int oplock = 0;
		/* open file */
		rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
				READ_CONTROL, 0, &fid, &oplock, NULL,
				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
					CIFS_MOUNT_MAP_SPECIAL_CHR);
		if (rc != 0) {
	int xid, rc;
	__u16 fid;

	xid = GetXid();

	rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, READ_CONTROL, 0,
			 &fid, &oplock, NULL, cifs_sb->local_nls,
			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
	if (rc) {
		cERROR(1, ("Unable to open file to get ACL"));
			FreeXid(xid);
			return NULL;
		}
		goto out;
	}

	rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
	cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
	if (unlock_file == true) /* find_readable_file increments ref count */
		atomic_dec(&open_file->wrtPending);
	else if (pfid == NULL) /* if opened above we have to close the handle */
		CIFSSMBClose(xid, cifs_sb->tcon, fid);
	/* else handle was passed in by caller */

	CIFSSMBClose(xid, cifs_sb->tcon, fid);
 out:
	FreeXid(xid);
	return pntsd;
}

/* Set an ACL on the server */
static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
				struct inode *inode, const char *path)
/* Retrieve an ACL from the server */
static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
				      struct inode *inode, const char *path,
				      u32 *pacllen)
{
	struct cifsFileInfo *open_file;
	bool unlock_file = false;
	int xid;
	int rc = -EIO;
	__u16 fid;
	struct super_block *sb;
	struct cifs_sb_info *cifs_sb;
	struct cifs_ntsd *pntsd = NULL;
	struct cifsFileInfo *open_file = NULL;

	cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode));
	if (inode)
		open_file = find_readable_file(CIFS_I(inode));
	if (!open_file)
		return get_cifs_acl_by_path(cifs_sb, path, pacllen);

	if (!inode)
		return rc;
	pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
	atomic_dec(&open_file->wrtPending);
	return pntsd;
}

	sb = inode->i_sb;
	if (sb == NULL)
		return rc;
static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
		struct cifs_ntsd *pnntsd, u32 acllen)
{
	int xid, rc;

	cifs_sb = CIFS_SB(sb);
	xid = GetXid();

	open_file = find_readable_file(CIFS_I(inode));
	if (open_file) {
		unlock_file = true;
		fid = open_file->netfid;
	} else {
		int oplock = 0;
		/* open file */
		rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
				WRITE_DAC, 0, &fid, &oplock, NULL,
				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
					CIFS_MOUNT_MAP_SPECIAL_CHR);
		if (rc != 0) {
			cERROR(1, ("Unable to open file to set ACL"));
	rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
	FreeXid(xid);

	cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
	return rc;
}

static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
		struct cifs_ntsd *pnntsd, u32 acllen)
{
	int oplock = 0;
	int xid, rc;
	__u16 fid;

	xid = GetXid();

	rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, WRITE_DAC, 0,
			 &fid, &oplock, NULL, cifs_sb->local_nls,
			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
	if (rc) {
		cERROR(1, ("Unable to open file to set ACL"));
		goto out;
	}

	rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
	cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
	if (unlock_file)
		atomic_dec(&open_file->wrtPending);
	else
		CIFSSMBClose(xid, cifs_sb->tcon, fid);

	CIFSSMBClose(xid, cifs_sb->tcon, fid);
 out:
	FreeXid(xid);
	return rc;
}

/* Set an ACL on the server */
static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
				struct inode *inode, const char *path)
{
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
	struct cifsFileInfo *open_file;
	int rc;

	cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode));

	open_file = find_readable_file(CIFS_I(inode));
	if (!open_file)
		return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);

	rc = set_cifs_acl_by_fid(cifs_sb, open_file->netfid, pnntsd, acllen);
	atomic_dec(&open_file->wrtPending);
	return rc;
}

/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid)
void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode,
		     const char *path, const __u16 *pfid)
{
	struct cifs_ntsd *pntsd = NULL;
	u32 acllen = 0;
	int rc = 0;

	cFYI(DBG2, ("converting ACL to mode for %s", path));
	pntsd = get_cifs_acl(&acllen, inode, path, pfid);

	if (pfid)
		pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
	else
		pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);

	/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
	if (pntsd)
@@ -698,7 +706,7 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
	cFYI(DBG2, ("set ACL from mode for %s", path));

	/* Get the security descriptor */
	pntsd = get_cifs_acl(&secdesclen, inode, path, NULL);
	pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);

	/* Add three ACEs for owner, group, everyone getting rid of
	   other ACEs as chmod disables ACEs and set the security descriptor */
+1 −1
Original line number Diff line number Diff line
@@ -146,7 +146,7 @@ cifs_read_super(struct super_block *sb, void *data,
#endif
	sb->s_blocksize = CIFS_MAX_MSGSIZE;
	sb->s_blocksize_bits = 14;	/* default 2**14 = CIFS_MAX_MSGSIZE */
	inode = cifs_iget(sb, ROOT_I);
	inode = cifs_root_iget(sb, ROOT_I);

	if (IS_ERR(inode)) {
		rc = PTR_ERR(inode);
Loading