]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 12 Nov 2007 19:12:06 +0000 (11:12 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 12 Nov 2007 19:12:06 +0000 (11:12 -0800)
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (39 commits)
  [INET]: Small possible memory leak in FIB rules
  [NETNS]: init dev_base_lock only once
  [UNIX]: The unix_nr_socks limit can be exceeded
  [AF_UNIX]: Convert socks to unix_socks in scan_inflight, not in callbacks
  [AF_UNIX]: Make unix_tot_inflight counter non-atomic
  [AF_PACKET]: Allow multicast traffic to be caught by ORIGDEV when bonded
  ssb: Fix PCMCIA-host lowlevel bus access
  mac80211: fix MAC80211_RCSIMPLE Kconfig
  mac80211: make "decrypt failed" messages conditional upon MAC80211_DEBUG
  mac80211: use IW_AUTH_PRIVACY_INVOKED rather than IW_AUTH_KEY_MGMT
  mac80211: remove unused driver ops
  mac80211: remove ieee80211_common.h
  softmac: MAINTAINERS update
  rfkill: Fix sparse warning
  rfkill: Use mutex_lock() at register and add sanity check
  iwlwifi: select proper rate control algorithm
  mac80211: allow driver to ask for a rate control algorithm
  mac80211: don't allow registering the same rate control twice
  rfkill: Use subsys_initcall
  mac80211: make simple rate control algorithm built-in
  ...

28 files changed:
arch/x86/kernel/i387_64.c
fs/Kconfig
fs/cifs/CHANGES
fs/cifs/Makefile
fs/cifs/asn1.c
fs/cifs/cifs_spnego.c [new file with mode: 0644]
fs/cifs/cifs_spnego.h [new file with mode: 0644]
fs/cifs/cifsacl.c
fs/cifs/cifsacl.h
fs/cifs/cifsencrypt.c
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifspdu.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/md5.c
fs/cifs/misc.c
fs/cifs/netmisc.c
fs/cifs/readdir.c
fs/cifs/smbencrypt.c
fs/cifs/xattr.c
fs/exec.c
include/asm-x86/i387_64.h
mm/slub.c

index 56c1f11471099103292b5aa291a388113d27fa9b..bfaff28fb1348f41f14b7caadf363ca86879595e 100644 (file)
@@ -92,13 +92,14 @@ int save_i387(struct _fpstate __user *buf)
        if (task_thread_info(tsk)->status & TS_USEDFPU) {
                err = save_i387_checking((struct i387_fxsave_struct __user *)buf);
                if (err) return err;
+               task_thread_info(tsk)->status &= ~TS_USEDFPU;
                stts();
-               } else {
-               if (__copy_to_user(buf, &tsk->thread.i387.fxsave, 
+       } else {
+               if (__copy_to_user(buf, &tsk->thread.i387.fxsave,
                                   sizeof(struct i387_fxsave_struct)))
                        return -1;
-       } 
-               return 1;
+       }
+       return 1;
 }
 
 /*
index c75c95406497f5173e449f3571fda8db8daef360..429a002285075c7556b30f1364a3d091a3052c57 100644 (file)
@@ -2007,7 +2007,7 @@ config CIFS_EXPERIMENTAL
 config CIFS_UPCALL
          bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
          depends on CIFS_EXPERIMENTAL
-         depends on CONNECTOR
+         depends on KEYS
          help
            Enables an upcall mechanism for CIFS which will be used to contact
            userspace helper utilities to provide SPNEGO packaged Kerberos
index 3d419163c3d3a345f0a3bd06b230f0186038d60b..64dd22239b21b4a7181b6c719ae091b76fc7b30d 100644 (file)
@@ -1,3 +1,7 @@
+Version 1.52
+------------
+Fix oops on second mount to server when null auth is used.
+
 Version 1.51
 ------------
 Fix memory leak in statfs when mounted to very old servers (e.g.
@@ -12,7 +16,12 @@ leak that causes cifsd not to stop and rmmod to fail to cleanup
 cifs_request_buffers pool. Fix problem with POSIX Open/Mkdir on
 bigendian architectures. Fix possible memory corruption when
 EAGAIN returned on kern_recvmsg. Return better error if server
-requires packet signing but client has disabled it.
+requires packet signing but client has disabled it. When mounted
+with cifsacl mount option - mode bits are approximated based
+on the contents of the ACL of the file or directory. When cifs
+mount helper is missing convert make sure that UNC name 
+has backslash (not forward slash) between ip address of server
+and the share name.
 
 Version 1.50
 ------------
index ff6ba8d823f03a91b3ffad88202c75708d1c9eba..45e42fb97c19e9df3750ac0adc8817b2f251a425 100644 (file)
@@ -3,4 +3,9 @@
 #
 obj-$(CONFIG_CIFS) += cifs.o
 
-cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o export.o cifsacl.o
+cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \
+         link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \
+         md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o \
+         readdir.o ioctl.o sess.o export.o cifsacl.o
+
+cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
index 2a01f3ef96a0503332da509b81e4c788f07113c2..bcda2c6b6a048db68697246a61040e41f6b35da6 100644 (file)
 
 #define SPNEGO_OID_LEN 7
 #define NTLMSSP_OID_LEN  10
+#define KRB5_OID_LEN  7
+#define MSKRB5_OID_LEN  7
 static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
 static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
+static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 };
+static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 };
 
 /*
  * ASN.1 context.
@@ -457,6 +461,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
        unsigned long *oid = NULL;
        unsigned int cls, con, tag, oidlen, rc;
        int use_ntlmssp = FALSE;
+       int use_kerberos = FALSE;
 
        *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/
 
@@ -545,18 +550,28 @@ decode_negTokenInit(unsigned char *security_blob, int length,
                                return 0;
                        }
                        if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
-                               rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
-                               if (rc) {
+                               if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) {
+
                                        cFYI(1,
                                          ("OID len = %d oid = 0x%lx 0x%lx "
                                           "0x%lx 0x%lx",
                                           oidlen, *oid, *(oid + 1),
                                           *(oid + 2), *(oid + 3)));
-                                       rc = compare_oid(oid, oidlen,
-                                                NTLMSSP_OID, NTLMSSP_OID_LEN);
-                                       kfree(oid);
-                                       if (rc)
+
+                                       if (compare_oid(oid, oidlen,
+                                                       MSKRB5_OID,
+                                                       MSKRB5_OID_LEN))
+                                               use_kerberos = TRUE;
+                                       else if (compare_oid(oid, oidlen,
+                                                            KRB5_OID,
+                                                            KRB5_OID_LEN))
+                                               use_kerberos = TRUE;
+                                       else if (compare_oid(oid, oidlen,
+                                                            NTLMSSP_OID,
+                                                            NTLMSSP_OID_LEN))
                                                use_ntlmssp = TRUE;
+
+                                       kfree(oid);
                                }
                        } else {
                                cFYI(1, ("Should be an oid what is going on?"));
@@ -609,12 +624,10 @@ decode_negTokenInit(unsigned char *security_blob, int length,
                         ctx.pointer)); /* is this UTF-8 or ASCII? */
        }
 
-       /* if (use_kerberos)
-          *secType = Kerberos
-          else */
-       if (use_ntlmssp) {
+       if (use_kerberos)
+               *secType = Kerberos;
+       else if (use_ntlmssp)
                *secType = NTLMSSP;
-       }
 
        return 1;
 }
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
new file mode 100644 (file)
index 0000000..ad54a3a
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ *   fs/cifs/cifs_spnego.c -- SPNEGO upcall management for CIFS
+ *
+ *   Copyright (c) 2007 Red Hat, Inc.
+ *   Author(s): Jeff Layton (jlayton@redhat.com)
+ *
+ *   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
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/list.h>
+#include <linux/string.h>
+#include <keys/user-type.h>
+#include <linux/key-type.h>
+#include "cifsglob.h"
+#include "cifs_spnego.h"
+#include "cifs_debug.h"
+
+/* create a new cifs key */
+static int
+cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen)
+{
+       char *payload;
+       int ret;
+
+       ret = -ENOMEM;
+       payload = kmalloc(datalen, GFP_KERNEL);
+       if (!payload)
+               goto error;
+
+       /* attach the data */
+       memcpy(payload, data, datalen);
+       rcu_assign_pointer(key->payload.data, payload);
+       ret = 0;
+
+error:
+       return ret;
+}
+
+static void
+cifs_spnego_key_destroy(struct key *key)
+{
+       kfree(key->payload.data);
+}
+
+
+/*
+ * keytype for CIFS spnego keys
+ */
+struct key_type cifs_spnego_key_type = {
+       .name           = "cifs.spnego",
+       .instantiate    = cifs_spnego_key_instantiate,
+       .match          = user_match,
+       .destroy        = cifs_spnego_key_destroy,
+       .describe       = user_describe,
+};
+
+/* get a key struct with a SPNEGO security blob, suitable for session setup */
+struct key *
+cifs_get_spnego_key(struct cifsSesInfo *sesInfo, const char *hostname)
+{
+       struct TCP_Server_Info *server = sesInfo->server;
+       char *description, *dp;
+       size_t desc_len;
+       struct key *spnego_key;
+
+
+       /* version + ;ip{4|6}= + address + ;host=hostname +
+               ;sec= + ;uid= + NULL */
+       desc_len = 4 + 5 + 32 + 1 + 5 + strlen(hostname) +
+                  strlen(";sec=krb5") + 7 + sizeof(uid_t)*2 + 1;
+       spnego_key = ERR_PTR(-ENOMEM);
+       description = kzalloc(desc_len, GFP_KERNEL);
+       if (description == NULL)
+               goto out;
+
+       dp = description;
+       /* start with version and hostname portion of UNC string */
+       spnego_key = ERR_PTR(-EINVAL);
+       sprintf(dp, "0x%2.2x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION,
+               hostname);
+       dp = description + strlen(description);
+
+       /* add the server address */
+       if (server->addr.sockAddr.sin_family == AF_INET)
+               sprintf(dp, "ip4=" NIPQUAD_FMT,
+                       NIPQUAD(server->addr.sockAddr.sin_addr));
+       else if (server->addr.sockAddr.sin_family == AF_INET6)
+               sprintf(dp, "ip6=" NIP6_SEQFMT,
+                       NIP6(server->addr.sockAddr6.sin6_addr));
+       else
+               goto out;
+
+       dp = description + strlen(description);
+
+       /* for now, only sec=krb5 is valid */
+       if (server->secType == Kerberos)
+               sprintf(dp, ";sec=krb5");
+       else
+               goto out;
+
+       dp = description + strlen(description);
+       sprintf(dp, ";uid=0x%x", sesInfo->linux_uid);
+
+       cFYI(1, ("key description = %s", description));
+       spnego_key = request_key(&cifs_spnego_key_type, description, "");
+
+       if (cifsFYI && !IS_ERR(spnego_key)) {
+               struct cifs_spnego_msg *msg = spnego_key->payload.data;
+               cifs_dump_mem("SPNEGO reply blob:", msg->data,
+                               msg->secblob_len + msg->sesskey_len);
+       }
+
+out:
+       kfree(description);
+       return spnego_key;
+}
diff --git a/fs/cifs/cifs_spnego.h b/fs/cifs/cifs_spnego.h
new file mode 100644 (file)
index 0000000..f443f3b
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *   fs/cifs/cifs_spnego.h -- SPNEGO upcall management for CIFS
+ *
+ *   Copyright (c) 2007 Red Hat, Inc.
+ *   Author(s): Jeff Layton (jlayton@redhat.com)
+ *              Steve French (sfrench@us.ibm.com)
+ *
+ *   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
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _CIFS_SPNEGO_H
+#define _CIFS_SPNEGO_H
+
+#define CIFS_SPNEGO_UPCALL_VERSION 1
+
+/*
+ * The version field should always be set to CIFS_SPNEGO_UPCALL_VERSION.
+ * The flags field is for future use. The request-key callout should set
+ * sesskey_len and secblob_len, and then concatenate the SessKey+SecBlob
+ * and stuff it in the data field.
+ */
+struct cifs_spnego_msg {
+       uint32_t        version;
+       uint32_t        flags;
+       uint32_t        sesskey_len;
+       uint32_t        secblob_len;
+       uint8_t         data[1];
+};
+
+#ifdef __KERNEL__
+extern struct key_type cifs_spnego_key_type;
+#endif /* KERNEL */
+
+#endif /* _CIFS_SPNEGO_H */
index e8e56353f5a1c423b5e6e70f986bbb8b6a3f7a19..dabbce00712b0f23e02e5bfe46e5696850791e1f 100644 (file)
@@ -38,13 +38,13 @@ static struct cifs_wksid wksidarr[NUM_WK_SIDS] = {
        {{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(18), 0, 0, 0, 0} }, "sys"},
        {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(544), 0, 0, 0} }, "root"},
        {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(545), 0, 0, 0} }, "users"},
-       {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(546), 0, 0, 0} }, "guest"}
-};
+       {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(546), 0, 0, 0} }, "guest"} }
+;
 
 
 /* security id for everyone */
-static const struct cifs_sid sid_everyone =
-               {1, 1, {0, 0, 0, 0, 0, 0}, {} };
+static const struct cifs_sid sid_everyone = {
+       1, 1, {0, 0, 0, 0, 0, 1}, {0} };
 /* group users */
 static const struct cifs_sid sid_user =
                {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
@@ -97,7 +97,7 @@ int match_sid(struct cifs_sid *ctsid)
 
 /* if the two SIDs (roughly equivalent to a UUID for a user or group) are
    the same returns 1, if they do not match returns 0 */
-int compare_sids(struct cifs_sid *ctsid, struct cifs_sid *cwsid)
+int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
 {
        int i;
        int num_subauth, num_sat, num_saw;
@@ -129,66 +129,142 @@ int compare_sids(struct cifs_sid *ctsid, struct cifs_sid *cwsid)
        return (1); /* sids compare/match */
 }
 
+/*
+   change posix mode to reflect permissions
+   pmode is the existing mode (we only want to overwrite part of this
+   bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
+*/
+static void access_flags_to_mode(__u32 ace_flags, int type, umode_t *pmode,
+                                umode_t *pbits_to_set)
+{
+       /* the order of ACEs is important.  The canonical order is to begin with
+          DENY entries followed by ALLOW, otherwise an allow entry could be
+          encountered first, making the subsequent deny entry like "dead code"
+          which would be superflous since Windows stops when a match is made
+          for the operation you are trying to perform for your user */
+
+       /* For deny ACEs we change the mask so that subsequent allow access
+          control entries do not turn on the bits we are denying */
+       if (type == ACCESS_DENIED) {
+               if (ace_flags & GENERIC_ALL) {
+                       *pbits_to_set &= ~S_IRWXUGO;
+               }
+               if ((ace_flags & GENERIC_WRITE) ||
+                       ((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
+                       *pbits_to_set &= ~S_IWUGO;
+               if ((ace_flags & GENERIC_READ) ||
+                       ((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
+                       *pbits_to_set &= ~S_IRUGO;
+               if ((ace_flags & GENERIC_EXECUTE) ||
+                       ((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
+                       *pbits_to_set &= ~S_IXUGO;
+               return;
+       } else if (type != ACCESS_ALLOWED) {
+               cERROR(1, ("unknown access control type %d", type));
+               return;
+       }
+       /* else ACCESS_ALLOWED type */
+
+       if (ace_flags & GENERIC_ALL) {
+               *pmode |= (S_IRWXUGO & (*pbits_to_set));
+#ifdef CONFIG_CIFS_DEBUG2
+               cFYI(1, ("all perms"));
+#endif
+               return;
+       }
+       if ((ace_flags & GENERIC_WRITE) ||
+                       ((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
+               *pmode |= (S_IWUGO & (*pbits_to_set));
+       if ((ace_flags & GENERIC_READ) ||
+                       ((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
+               *pmode |= (S_IRUGO & (*pbits_to_set));
+       if ((ace_flags & GENERIC_EXECUTE) ||
+                       ((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
+               *pmode |= (S_IXUGO & (*pbits_to_set));
+
+#ifdef CONFIG_CIFS_DEBUG2
+       cFYI(1, ("access flags 0x%x mode now 0x%x", ace_flags, *pmode));
+#endif
+       return;
+}
+
+/*
+   Generate access flags to reflect permissions mode is the existing mode.
+   This function is called for every ACE in the DACL whose SID matches
+   with either owner or group or everyone.
+*/
+
+static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
+                               __u32 *pace_flags)
+{
+       /* reset access mask */
+       *pace_flags = 0x0;
+
+       /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
+       mode &= bits_to_use;
+
+       /* check for R/W/X UGO since we do not know whose flags
+          is this but we have cleared all the bits sans RWX for
+          either user or group or other as per bits_to_use */
+       if (mode & S_IRUGO)
+               *pace_flags |= SET_FILE_READ_RIGHTS;
+       if (mode & S_IWUGO)
+               *pace_flags |= SET_FILE_WRITE_RIGHTS;
+       if (mode & S_IXUGO)
+               *pace_flags |= SET_FILE_EXEC_RIGHTS;
+
+#ifdef CONFIG_CIFS_DEBUG2
+       cFYI(1, ("mode: 0x%x, access flags now 0x%x", mode, *pace_flags));
+#endif
+       return;
+}
+
 
-static void parse_ace(struct cifs_ace *pace, char *end_of_acl)
+#ifdef CONFIG_CIFS_DEBUG2
+static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
 {
        int num_subauth;
 
        /* validate that we do not go past end of acl */
 
-       /* XXX this if statement can be removed
-       if (end_of_acl < (char *)pace + sizeof(struct cifs_ace)) {
+       if (le16_to_cpu(pace->size) < 16) {
+               cERROR(1, ("ACE too small, %d", le16_to_cpu(pace->size)));
+               return;
+       }
+
+       if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
                cERROR(1, ("ACL too small to parse ACE"));
                return;
-       } */
+       }
 
-       num_subauth = pace->num_subauth;
+       num_subauth = pace->sid.num_subauth;
        if (num_subauth) {
-#ifdef CONFIG_CIFS_DEBUG2
                int i;
-               cFYI(1, ("ACE revision %d num_subauth %d",
-                       pace->revision, pace->num_subauth));
+               cFYI(1, ("ACE revision %d num_auth %d type %d flags %d size %d",
+                       pace->sid.revision, pace->sid.num_subauth, pace->type,
+                       pace->flags, pace->size));
                for (i = 0; i < num_subauth; ++i) {
                        cFYI(1, ("ACE sub_auth[%d]: 0x%x", i,
-                               le32_to_cpu(pace->sub_auth[i])));
+                               le32_to_cpu(pace->sid.sub_auth[i])));
                }
 
                /* BB add length check to make sure that we do not have huge
                        num auths and therefore go off the end */
-
-               cFYI(1, ("RID %d", le32_to_cpu(pace->sub_auth[num_subauth-1])));
-#endif
        }
 
        return;
 }
-
-static void parse_ntace(struct cifs_ntace *pntace, char *end_of_acl)
-{
-       /* validate that we do not go past end of acl */
-       if (end_of_acl < (char *)pntace + sizeof(struct cifs_ntace)) {
-               cERROR(1, ("ACL too small to parse NT ACE"));
-               return;
-       }
-
-#ifdef CONFIG_CIFS_DEBUG2
-       cFYI(1, ("NTACE type %d flags 0x%x size %d, access Req 0x%x",
-               pntace->type, pntace->flags, pntace->size,
-               pntace->access_req));
 #endif
-       return;
-}
-
 
 
 static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
-                      struct cifs_sid *pownersid, struct cifs_sid *pgrpsid)
+                      struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
+                      struct inode *inode)
 {
        int i;
        int num_aces = 0;
        int acl_size;
        char *acl_base;
-       struct cifs_ntace **ppntace;
        struct cifs_ace **ppace;
 
        /* BB need to add parm so we can store the SID BB */
@@ -205,50 +281,63 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
                le32_to_cpu(pdacl->num_aces)));
 #endif
 
+       /* reset rwx permissions for user/group/other.
+          Also, if num_aces is 0 i.e. DACL has no ACEs,
+          user/group/other have no permissions */
+       inode->i_mode &= ~(S_IRWXUGO);
+
+       if (!pdacl) {
+               /* no DACL in the security descriptor, set
+                  all the permissions for user/group/other */
+               inode->i_mode |= S_IRWXUGO;
+               return;
+       }
        acl_base = (char *)pdacl;
        acl_size = sizeof(struct cifs_acl);
 
        num_aces = le32_to_cpu(pdacl->num_aces);
        if (num_aces  > 0) {
-               ppntace = kmalloc(num_aces * sizeof(struct cifs_ntace *),
-                               GFP_KERNEL);
+               umode_t user_mask = S_IRWXU;
+               umode_t group_mask = S_IRWXG;
+               umode_t other_mask = S_IRWXO;
+
                ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
                                GFP_KERNEL);
 
 /*             cifscred->cecount = pdacl->num_aces;
-               cifscred->ntaces = kmalloc(num_aces *
-                       sizeof(struct cifs_ntace *), GFP_KERNEL);
                cifscred->aces = kmalloc(num_aces *
                        sizeof(struct cifs_ace *), GFP_KERNEL);*/
 
                for (i = 0; i < num_aces; ++i) {
-                       ppntace[i] = (struct cifs_ntace *)
-                                       (acl_base + acl_size);
-                       ppace[i] = (struct cifs_ace *) ((char *)ppntace[i] +
-                                       sizeof(struct cifs_ntace));
-
-                       parse_ntace(ppntace[i], end_of_acl);
-                       if (end_of_acl < ((char *)ppace[i] +
-                                       (le16_to_cpu(ppntace[i]->size) -
-                                       sizeof(struct cifs_ntace)))) {
-                               cERROR(1, ("ACL too small to parse ACE"));
-                               break;
-                       } else
-                               parse_ace(ppace[i], end_of_acl);
-
-/*                     memcpy((void *)(&(cifscred->ntaces[i])),
-                               (void *)ppntace[i],
-                               sizeof(struct cifs_ntace));
-                       memcpy((void *)(&(cifscred->aces[i])),
+                       ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
+#ifdef CONFIG_CIFS_DEBUG2
+                       dump_ace(ppace[i], end_of_acl);
+#endif
+                       if (compare_sids(&(ppace[i]->sid), pownersid))
+                               access_flags_to_mode(ppace[i]->access_req,
+                                                    ppace[i]->type,
+                                                    &(inode->i_mode),
+                                                    &user_mask);
+                       if (compare_sids(&(ppace[i]->sid), pgrpsid))
+                               access_flags_to_mode(ppace[i]->access_req,
+                                                    ppace[i]->type,
+                                                    &(inode->i_mode),
+                                                    &group_mask);
+                       if (compare_sids(&(ppace[i]->sid), &sid_everyone))
+                               access_flags_to_mode(ppace[i]->access_req,
+                                                    ppace[i]->type,
+                                                    &(inode->i_mode),
+                                                    &other_mask);
+
+/*                     memcpy((void *)(&(cifscred->aces[i])),
                                (void *)ppace[i],
                                sizeof(struct cifs_ace)); */
 
-                       acl_base = (char *)ppntace[i];
-                       acl_size = le16_to_cpu(ppntace[i]->size);
+                       acl_base = (char *)ppace[i];
+                       acl_size = le16_to_cpu(ppace[i]->size);
                }
 
                kfree(ppace);
-               kfree(ppntace);
        }
 
        return;
@@ -257,20 +346,20 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
 
 static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
 {
-
        /* BB need to add parm so we can store the SID BB */
 
-       /* validate that we do not go past end of acl */
-       if (end_of_acl < (char *)psid + sizeof(struct cifs_sid)) {
-               cERROR(1, ("ACL too small to parse SID"));
+       /* validate that we do not go past end of ACL - sid must be at least 8
+          bytes long (assuming no sub-auths - e.g. the null SID */
+       if (end_of_acl < (char *)psid + 8) {
+               cERROR(1, ("ACL too small to parse SID %p", psid));
                return -EINVAL;
        }
 
        if (psid->num_subauth) {
 #ifdef CONFIG_CIFS_DEBUG2
                int i;
-               cFYI(1, ("SID revision %d num_auth %d First subauth 0x%x",
-                       psid->revision, psid->num_subauth, psid->sub_auth[0]));
+               cFYI(1, ("SID revision %d num_auth %d",
+                       psid->revision, psid->num_subauth));
 
                for (i = 0; i < psid->num_subauth; i++) {
                        cFYI(1, ("SID sub_auth[%d]: 0x%x ", i,
@@ -289,27 +378,32 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
 
 
 /* Convert CIFS ACL to POSIX form */
-int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len)
+static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
+                         struct inode *inode)
 {
        int rc;
        struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
        struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
        char *end_of_acl = ((char *)pntsd) + acl_len;
+       __u32 dacloffset;
+
+       if ((inode == NULL) || (pntsd == NULL))
+               return -EIO;
 
        owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
                                le32_to_cpu(pntsd->osidoffset));
        group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
                                le32_to_cpu(pntsd->gsidoffset));
-       dacl_ptr = (struct cifs_acl *)((char *)pntsd +
-                               le32_to_cpu(pntsd->dacloffset));
+       dacloffset = le32_to_cpu(pntsd->dacloffset);
+       dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
 #ifdef CONFIG_CIFS_DEBUG2
        cFYI(1, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x "
                 "sacloffset 0x%x dacloffset 0x%x",
                 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
                 le32_to_cpu(pntsd->gsidoffset),
-                le32_to_cpu(pntsd->sacloffset),
-                le32_to_cpu(pntsd->dacloffset)));
+                le32_to_cpu(pntsd->sacloffset), dacloffset));
 #endif
+/*     cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
        rc = parse_sid(owner_sid_ptr, end_of_acl);
        if (rc)
                return rc;
@@ -318,16 +412,120 @@ int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len)
        if (rc)
                return rc;
 
-       parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr);
+       if (dacloffset)
+               parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
+                          group_sid_ptr, inode);
+       else
+               cFYI(1, ("no ACL")); /* BB grant all or default perms? */
 
 /*     cifscred->uid = owner_sid_ptr->rid;
        cifscred->gid = group_sid_ptr->rid;
        memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
-                       sizeof (struct cifs_sid));
+                       sizeof(struct cifs_sid));
        memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
-                       sizeof (struct cifs_sid)); */
+                       sizeof(struct cifs_sid)); */
 
 
        return (0);
 }
+
+
+/* Retrieve an ACL from the server */
+static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
+                                      const char *path)
+{
+       struct cifsFileInfo *open_file;
+       int 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;
+
+       xid = GetXid();
+       open_file = find_readable_file(CIFS_I(inode));
+       sb = inode->i_sb;
+       if (sb == NULL) {
+               FreeXid(xid);
+               return NULL;
+       }
+       cifs_sb = CIFS_SB(sb);
+
+       if (open_file) {
+               unlock_file = TRUE;
+               fid = open_file->netfid;
+       } else {
+               int oplock = FALSE;
+               /* 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) {
+                       cERROR(1, ("Unable to open file to get ACL"));
+                       FreeXid(xid);
+                       return NULL;
+               }
+       }
+
+       rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
+       cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
+       if (unlock_file == TRUE)
+               atomic_dec(&open_file->wrtPending);
+       else
+               CIFSSMBClose(xid, cifs_sb->tcon, fid);
+
+       FreeXid(xid);
+       return pntsd;
+}
+
+/* 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)
+{
+       struct cifs_ntsd *pntsd = NULL;
+       u32 acllen = 0;
+       int rc = 0;
+
+#ifdef CONFIG_CIFS_DEBUG2
+       cFYI(1, ("converting ACL to mode for %s", path));
+#endif
+       pntsd = get_cifs_acl(&acllen, inode, path);
+
+       /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
+       if (pntsd)
+               rc = parse_sec_desc(pntsd, acllen, inode);
+       if (rc)
+               cFYI(1, ("parse sec desc failed rc = %d", rc));
+
+       kfree(pntsd);
+       return;
+}
+
+/* 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)
+{
+       int rc = 0;
+       __u32 acllen = 0;
+       struct cifs_ntsd *pntsd = NULL;
+
+       cFYI(1, ("set ACL from mode for %s", path));
+
+       /* Get the security descriptor */
+       pntsd = get_cifs_acl(&acllen, inode, path);
+
+       /* Add/Modify the three ACEs for owner, group, everyone
+          while retaining the other ACEs */
+
+       /* Set the security descriptor */
+
+
+       kfree(pntsd);
+       return rc;
+}
 #endif /* CONFIG_CIFS_EXPERIMENTAL */
index 420f87813647b9b9307ce484b3813f59180247a4..93a7c3462ea27c7c3080bbc963f545ba51fe1286 100644 (file)
@@ -35,6 +35,9 @@
 #define UBITSHIFT      6
 #define GBITSHIFT      3
 
+#define ACCESS_ALLOWED 0
+#define ACCESS_DENIED  1
+
 struct cifs_ntsd {
        __le16 revision; /* revision level */
        __le16 type;
@@ -48,7 +51,7 @@ struct cifs_sid {
        __u8 revision; /* revision level */
        __u8 num_subauth;
        __u8 authority[6];
-       __le32 sub_auth[5]; /* sub_auth[num_subauth] */ /* BB FIXME endianness BB */
+       __le32 sub_auth[5]; /* sub_auth[num_subauth] */
 } __attribute__((packed));
 
 struct cifs_acl {
@@ -57,18 +60,12 @@ struct cifs_acl {
        __le32 num_aces;
 } __attribute__((packed));
 
-struct cifs_ntace { /* first part of ACE which contains perms */
+struct cifs_ace {
        __u8 type;
        __u8 flags;
        __le16 size;
        __le32 access_req;
-} __attribute__((packed));
-
-struct cifs_ace { /* last part of ACE which includes user info */
-       __u8 revision; /* revision level */
-       __u8 num_subauth;
-       __u8 authority[6];
-       __le32 sub_auth[5];
+       struct cifs_sid sid; /* ie UUID of user or group who gets these perms */
 } __attribute__((packed));
 
 struct cifs_wksid {
@@ -79,7 +76,7 @@ struct cifs_wksid {
 #ifdef CONFIG_CIFS_EXPERIMENTAL
 
 extern int match_sid(struct cifs_sid *);
-extern int compare_sids(struct cifs_sid *, struct cifs_sid *);
+extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *);
 
 #endif /*  CONFIG_CIFS_EXPERIMENTAL */
 
index 632070b4275d91ba46baa1d735b578aeca555462..4ff8939c6cc7b51543170ab8c28d4a54d450f483 100644 (file)
@@ -99,15 +99,16 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
        MD5Init(&context);
        MD5Update(&context, (char *)&key->data, key->len);
        for (i = 0; i < n_vec; i++) {
+               if (iov[i].iov_len == 0)
+                       continue;
                if (iov[i].iov_base == NULL) {
                        cERROR(1, ("null iovec entry"));
                        return -EIO;
-               } else if (iov[i].iov_len == 0)
-                       break; /* bail out if we are sent nothing to sign */
+               }
                /* The first entry includes a length field (which does not get
                   signed that occupies the first 4 bytes before the header */
                if (i == 0) {
-                       if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */
+                       if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
                                break; /* nothing to sign or corrupt header */
                        MD5Update(&context, iov[0].iov_base+4,
                                  iov[0].iov_len-4);
@@ -122,7 +123,7 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
 
 
 int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
-                  __u32 * pexpected_response_sequence_number)
+                  __u32 *pexpected_response_sequence_number)
 {
        int rc = 0;
        char smb_signature[20];
index a6fbea57c4b1e6d895375ed10e8ef636995d763e..416dc9fe8961ac4e2e0c4eaebbaec7d1e186a739 100644 (file)
@@ -43,6 +43,8 @@
 #include "cifs_debug.h"
 #include "cifs_fs_sb.h"
 #include <linux/mm.h>
+#include <linux/key-type.h>
+#include "cifs_spnego.h"
 #define CIFS_MAGIC_NUMBER 0xFF534D42   /* the first four bytes of SMB PDUs */
 
 #ifdef CONFIG_CIFS_QUOTA
@@ -1005,12 +1007,16 @@ init_cifs(void)
        rc = register_filesystem(&cifs_fs_type);
        if (rc)
                goto out_destroy_request_bufs;
-
+#ifdef CONFIG_CIFS_UPCALL
+       rc = register_key_type(&cifs_spnego_key_type);
+       if (rc)
+               goto out_unregister_filesystem;
+#endif
        oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd");
        if (IS_ERR(oplockThread)) {
                rc = PTR_ERR(oplockThread);
                cERROR(1, ("error %d create oplock thread", rc));
-               goto out_unregister_filesystem;
+               goto out_unregister_key_type;
        }
 
        dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
@@ -1024,7 +1030,11 @@ init_cifs(void)
 
  out_stop_oplock_thread:
        kthread_stop(oplockThread);
+ out_unregister_key_type:
+#ifdef CONFIG_CIFS_UPCALL
+       unregister_key_type(&cifs_spnego_key_type);
  out_unregister_filesystem:
+#endif
        unregister_filesystem(&cifs_fs_type);
  out_destroy_request_bufs:
        cifs_destroy_request_bufs();
@@ -1045,6 +1055,9 @@ exit_cifs(void)
        cFYI(0, ("exit_cifs"));
 #ifdef CONFIG_PROC_FS
        cifs_proc_clean();
+#endif
+#ifdef CONFIG_CIFS_UPCALL
+       unregister_key_type(&cifs_spnego_key_type);
 #endif
        unregister_filesystem(&cifs_fs_type);
        cifs_destroy_inodecache();
index 5574ba3ab1f9c3c669b5f3e606bff729bcc2ebd6..2a21dc66f0de20be9544887d6312aa9b3394bac1 100644 (file)
@@ -106,5 +106,5 @@ extern int cifs_ioctl(struct inode *inode, struct file *filep,
 extern const struct export_operations cifs_export_ops;
 #endif /* EXPERIMENTAL */
 
-#define CIFS_VERSION   "1.51"
+#define CIFS_VERSION   "1.52"
 #endif                         /* _CIFSFS_H */
index c41ff74e9128b91af914930334b241fd3c0d313f..dbe6b846f37f0f476d83d59804aefde6e4d75881 100644 (file)
                                | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
 #define FILE_EXEC_RIGHTS (FILE_EXECUTE)
 
+#define SET_FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_WRITE_EA \
+                               | FILE_READ_ATTRIBUTES \
+                               | FILE_WRITE_ATTRIBUTES \
+                               | DELETE | READ_CONTROL | WRITE_DAC \
+                               | WRITE_OWNER | SYNCHRONIZE)
+#define SET_FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
+                               | FILE_READ_EA | FILE_WRITE_EA \
+                               | FILE_DELETE_CHILD | FILE_READ_ATTRIBUTES \
+                               | FILE_WRITE_ATTRIBUTES \
+                               | DELETE | READ_CONTROL | WRITE_DAC \
+                               | WRITE_OWNER | SYNCHRONIZE)
+#define SET_FILE_EXEC_RIGHTS (FILE_READ_EA | FILE_WRITE_EA | FILE_EXECUTE \
+                               | FILE_READ_ATTRIBUTES \
+                               | FILE_WRITE_ATTRIBUTES \
+                               | DELETE | READ_CONTROL | WRITE_DAC \
+                               | WRITE_OWNER | SYNCHRONIZE)
+
 
 /*
  * Invalid readdir handle
@@ -1211,6 +1228,29 @@ typedef struct smb_com_transaction_qsec_req {
        __le32 AclFlags;
 } __attribute__((packed)) QUERY_SEC_DESC_REQ;
 
+
+typedef struct smb_com_transaction_ssec_req {
+       struct smb_hdr hdr;     /* wct = 19 */
+       __u8 MaxSetupCount;
+       __u16 Reserved;
+       __le32 TotalParameterCount;
+       __le32 TotalDataCount;
+       __le32 MaxParameterCount;
+       __le32 MaxDataCount;
+       __le32 ParameterCount;
+       __le32 ParameterOffset;
+       __le32 DataCount;
+       __le32 DataOffset;
+       __u8 SetupCount; /* no setup words follow subcommand */
+       /* SNIA spec incorrectly included spurious pad here */
+       __le16 SubCommand; /* 3 = SET_SECURITY_DESC */
+       __le16 ByteCount; /* bcc = 3 + 8 */
+       __u8 Pad[3];
+       __u16 Fid;
+       __u16 Reserved2;
+       __le32 AclFlags;
+} __attribute__((packed)) SET_SEC_DESC_REQ;
+
 typedef struct smb_com_transaction_change_notify_req {
        struct smb_hdr hdr;     /* wct = 23 */
        __u8 MaxSetupCount;
index 1a883663b22dfcc51eac71da6fc8930bf5b7d3e6..dd1d7c200ee63a30e6496d1bbe0f5e153391346e 100644 (file)
@@ -61,6 +61,9 @@ extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length);
 extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
 extern int is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
 extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *);
+#endif
 extern unsigned int smbCalcSize(struct smb_hdr *ptr);
 extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
 extern int decode_negTokenInit(unsigned char *security_blob, int length,
@@ -73,6 +76,8 @@ extern void header_assemble(struct smb_hdr *, char /* command */ ,
 extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
                                struct cifsSesInfo *ses,
                                void **request_buf);
+extern struct key *cifs_get_spnego_key(struct cifsSesInfo *sesInfo,
+                                       const char *hostname);
 extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
                             const int stage,
                             const struct nls_table *nls_cp);
@@ -92,6 +97,8 @@ extern int cifs_get_inode_info(struct inode **pinode,
 extern int cifs_get_inode_info_unix(struct inode **pinode,
                        const unsigned char *search_path,
                        struct super_block *sb, int xid);
+extern void acl_to_uid_mode(struct inode *inode, const char *search_path);
+extern int mode_to_acl(struct inode *inode, const char *path);
 
 extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
                        const char *);
@@ -311,7 +318,6 @@ extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key);
 #endif /* CIFS_WEAK_PW_HASH */
-extern int parse_sec_desc(struct cifs_ntsd *, int);
 extern int CIFSSMBCopy(int xid,
                        struct cifsTconInfo *source_tcon,
                        const char *fromName,
@@ -336,8 +342,7 @@ extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
                const void *ea_value, const __u16 ea_value_len,
                const struct nls_table *nls_codepage, int remap_special_chars);
 extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon,
-                       __u16 fid, char *acl_inf, const int buflen,
-                       const int acl_type /* ACCESS vs. DEFAULT */);
+                       __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen);
 extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
                const unsigned char *searchName,
                char *acl_inf, const int buflen, const int acl_type,
index f0d9a485d0951f29c3f140ebda33391d7471a53d..59d7b7c037adafa4eac1357c62cc87eff1c1bcc7 100644 (file)
@@ -647,8 +647,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                                                 count - 16,
                                                 &server->secType);
                        if (rc == 1) {
-                       /* BB Need to fill struct for sessetup here */
-                               rc = -EOPNOTSUPP;
+                               rc = 0;
                        } else {
                                rc = -EINVAL;
                        }
@@ -2486,6 +2485,7 @@ querySymLinkRetry:
        return rc;
 }
 
+#ifdef CONFIG_CIFS_EXPERIMENTAL
 /* Initialize NT TRANSACT SMB into small smb request buffer.
    This assumes that all NT TRANSACTS that we init here have
    total parm and data under about 400 bytes (to fit in small cifs
@@ -2494,7 +2494,7 @@ querySymLinkRetry:
        MaxSetupCount (size of returned setup area) and
        MaxParameterCount (returned parms size) must be set by caller */
 static int
-smb_init_ntransact(const __u16 sub_command, const int setup_count,
+smb_init_nttransact(const __u16 sub_command, const int setup_count,
                   const int parm_len, struct cifsTconInfo *tcon,
                   void **ret_buf)
 {
@@ -2525,12 +2525,15 @@ smb_init_ntransact(const __u16 sub_command, const int setup_count,
 
 static int
 validate_ntransact(char *buf, char **ppparm, char **ppdata,
-                  int *pdatalen, int *pparmlen)
+                  __u32 *pparmlen, __u32 *pdatalen)
 {
        char *end_of_smb;
        __u32 data_count, data_offset, parm_count, parm_offset;
        struct smb_com_ntransact_rsp *pSMBr;
 
+       *pdatalen = 0;
+       *pparmlen = 0;
+
        if (buf == NULL)
                return -EINVAL;
 
@@ -2567,8 +2570,11 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata,
                cFYI(1, ("parm count and data count larger than SMB"));
                return -EINVAL;
        }
+       *pdatalen = data_count;
+       *pparmlen = parm_count;
        return 0;
 }
+#endif /* CIFS_EXPERIMENTAL */
 
 int
 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
@@ -3067,8 +3073,7 @@ GetExtAttrOut:
 /* Get Security Descriptor (by handle) from remote server for a file or dir */
 int
 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
-               /* BB fix up return info */ char *acl_inf, const int buflen,
-                 const int acl_type)
+                 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
 {
        int rc = 0;
        int buf_type = 0;
@@ -3077,7 +3082,10 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
 
        cFYI(1, ("GetCifsACL"));
 
-       rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
+       *pbuflen = 0;
+       *acl_inf = NULL;
+
+       rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
                        8 /* parm len */, tcon, (void **) &pSMB);
        if (rc)
                return rc;
@@ -3099,34 +3107,52 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
        if (rc) {
                cFYI(1, ("Send error in QuerySecDesc = %d", rc));
        } else {                /* decode response */
-               struct cifs_ntsd *psec_desc;
                __le32 * parm;
-               int parm_len;
-               int data_len;
-               int acl_len;
+               __u32 parm_len;
+               __u32 acl_len;
                struct smb_com_ntransact_rsp *pSMBr;
+               char *pdata;
 
 /* validate_nttransact */
                rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
-                                       (char **)&psec_desc,
-                                       &parm_len, &data_len);
+                                       &pdata, &parm_len, pbuflen);
                if (rc)
                        goto qsec_out;
                pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
 
-               cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, psec_desc));
+               cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
 
                if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
                        rc = -EIO;      /* bad smb */
+                       *pbuflen = 0;
                        goto qsec_out;
                }
 
 /* BB check that data area is minimum length and as big as acl_len */
 
                acl_len = le32_to_cpu(*parm);
-               /* BB check if (acl_len > bufsize) */
+               if (acl_len != *pbuflen) {
+                       cERROR(1, ("acl length %d does not match %d",
+                                  acl_len, *pbuflen));
+                       if (*pbuflen > acl_len)
+                               *pbuflen = acl_len;
+               }
 
-               parse_sec_desc(psec_desc, acl_len);
+               /* check if buffer is big enough for the acl
+                  header followed by the smallest SID */
+               if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
+                   (*pbuflen >= 64 * 1024)) {
+                       cERROR(1, ("bad acl length %d", *pbuflen));
+                       rc = -EINVAL;
+                       *pbuflen = 0;
+               } else {
+                       *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
+                       if (*acl_inf == NULL) {
+                               *pbuflen = 0;
+                               rc = -ENOMEM;
+                       }
+                       memcpy(*acl_inf, pdata, *pbuflen);
+               }
        }
 qsec_out:
        if (buf_type == CIFS_SMALL_BUFFER)
@@ -3381,7 +3407,7 @@ UnixQPathInfoRetry:
                        memcpy((char *) pFindData,
                               (char *) &pSMBr->hdr.Protocol +
                               data_offset,
-                              sizeof (FILE_UNIX_BASIC_INFO));
+                              sizeof(FILE_UNIX_BASIC_INFO));
                }
        }
        cifs_buf_release(pSMB);
@@ -3649,7 +3675,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
        pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
        pSMB->SearchHandle = searchHandle;      /* always kept as le */
        pSMB->SearchCount =
-               cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
+               cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
        pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
        pSMB->ResumeKey = psrch_inf->resume_key;
        pSMB->SearchFlags =
@@ -4331,7 +4357,7 @@ QFSDeviceRetry:
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
-               if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
+               if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
                        rc = -EIO;      /* bad smb */
                else {
                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
index 19ee11f7f35ad6188207d25edccb0af3b8cdad11..1102160f6661069e725345642f4af2c7439fe6fa 100644 (file)
@@ -793,7 +793,7 @@ cifs_parse_mount_options(char *options, const char *devname,
        vol->linux_gid = current->gid;
        vol->dir_mode = S_IRWXUGO;
        /* 2767 perms indicate mandatory locking support */
-       vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
+       vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP);
 
        /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
        vol->rw = TRUE;
@@ -1790,7 +1790,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
 
        if (volume_info.nullauth) {
                cFYI(1, ("null user"));
-               volume_info.username = NULL;
+               volume_info.username = "";
        } else if (volume_info.username) {
                /* BB fixme parse for domain name here */
                cFYI(1, ("Username: %s", volume_info.username));
index 793404b109252b7f589a1d5f11da8667e76379c2..37dc97af1487d2eed97fdfffa19f8f90c056830b 100644 (file)
@@ -593,7 +593,7 @@ static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
                 * case take precedence.  If a is not a negative dentry, this
                 * should have no side effects
                 */
-               memcpy((unsigned char *)a->name, b->name, a->len);
+               memcpy(a->name, b->name, a->len);
                return 0;
        }
        return 1;
index 1e7e4c06d9e3f8771f813064fcdc2bcce29596cc..68ad4ca0cfa3109fa155b1c7ef9527ba3bb0aed3 100644 (file)
@@ -1026,6 +1026,37 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
        return total_written;
 }
 
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
+{
+       struct cifsFileInfo *open_file = NULL;
+
+       read_lock(&GlobalSMBSeslock);
+       /* we could simply get the first_list_entry since write-only entries
+          are always at the end of the list but since the first entry might
+          have a close pending, we go through the whole list */
+       list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
+               if (open_file->closePend)
+                       continue;
+               if (open_file->pfile && ((open_file->pfile->f_flags & O_RDWR) ||
+                   (open_file->pfile->f_flags & O_RDONLY))) {
+                       if (!open_file->invalidHandle) {
+                               /* found a good file */
+                               /* lock it so it will not be closed on us */
+                               atomic_inc(&open_file->wrtPending);
+                               read_unlock(&GlobalSMBSeslock);
+                               return open_file;
+                       } /* else might as well continue, and look for
+                            another, or simply have the caller reopen it
+                            again rather than trying to fix this handle */
+               } else /* write only file */
+                       break; /* write only files are last so must be done */
+       }
+       read_unlock(&GlobalSMBSeslock);
+       return NULL;
+}
+#endif
+
 struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
 {
        struct cifsFileInfo *open_file;
index 5e8b388be3b672a7130e9e26f8bb954ed8321534..7d907e84e0327d01d531ef9fa142670de04b1ccb 100644 (file)
@@ -289,7 +289,7 @@ static int decode_sfu_inode(struct inode *inode, __u64 size,
 
 #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID)  /* SETFILEBITS valid bits */
 
-static int get_sfu_uid_mode(struct inode *inode,
+static int get_sfu_mode(struct inode *inode,
                        const unsigned char *path,
                        struct cifs_sb_info *cifs_sb, int xid)
 {
@@ -527,11 +527,16 @@ int cifs_get_inode_info(struct inode **pinode,
 
                /* BB fill in uid and gid here? with help from winbind?
                   or retrieve from NTFS stream extended attribute */
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+               /* fill in 0777 bits from ACL */
+               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
+                       cFYI(1, ("Getting mode bits from ACL"));
+                       acl_to_uid_mode(inode, search_path);
+               }
+#endif
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
-                       /* fill in uid, gid, mode from server ACL */
-                       /* BB FIXME this should also take into account the
-                        * default uid specified on mount if present */
-                       get_sfu_uid_mode(inode, search_path, cifs_sb, xid);
+                       /* fill in remaining high mode bits e.g. SUID, VTX */
+                       get_sfu_mode(inode, search_path, cifs_sb, xid);
                } else if (atomic_read(&cifsInfo->inUse) == 0) {
                        inode->i_uid = cifs_sb->mnt_uid;
                        inode->i_gid = cifs_sb->mnt_gid;
index e5c3e1212697a2253f4474b17b90371f462588ae..f13f96d42fcf63ebdfe4c76a1914a3d0afd03738 100644 (file)
@@ -276,8 +276,8 @@ hmac_md5_init_rfc2104(unsigned char *key, int key_len,
        }
 
        /* start out by storing key in pads */
-       memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
-       memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
+       memset(ctx->k_ipad, 0, sizeof(ctx->k_ipad));
+       memset(ctx->k_opad, 0, sizeof(ctx->k_opad));
        memcpy(ctx->k_ipad, key, key_len);
        memcpy(ctx->k_opad, key, key_len);
 
@@ -307,8 +307,8 @@ hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
        }
 
        /* start out by storing key in pads */
-       memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
-       memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
+       memset(ctx->k_ipad, 0, sizeof(ctx->k_ipad));
+       memset(ctx->k_opad, 0, sizeof(ctx->k_opad));
        memcpy(ctx->k_ipad, key, key_len);
        memcpy(ctx->k_opad, key, key_len);
 
index 51ec681fe74a2e32c19d90e2f45de591bb3ab048..15546c2354c5800b7930860304a0d043273db7fb 100644 (file)
@@ -73,7 +73,7 @@ sesInfoAlloc(void)
 {
        struct cifsSesInfo *ret_buf;
 
-       ret_buf = kzalloc(sizeof (struct cifsSesInfo), GFP_KERNEL);
+       ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL);
        if (ret_buf) {
                write_lock(&GlobalSMBSeslock);
                atomic_inc(&sesInfoAllocCount);
@@ -109,7 +109,7 @@ struct cifsTconInfo *
 tconInfoAlloc(void)
 {
        struct cifsTconInfo *ret_buf;
-       ret_buf = kzalloc(sizeof (struct cifsTconInfo), GFP_KERNEL);
+       ret_buf = kzalloc(sizeof(struct cifsTconInfo), GFP_KERNEL);
        if (ret_buf) {
                write_lock(&GlobalSMBSeslock);
                atomic_inc(&tconInfoAllocCount);
@@ -298,7 +298,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
        memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */
 
        buffer->smb_buf_length =
-           (2 * word_count) + sizeof (struct smb_hdr) -
+           (2 * word_count) + sizeof(struct smb_hdr) -
            4 /*  RFC 1001 length field does not count */  +
            2 /* for bcc field itself */ ;
        /* Note that this is the only network field that has to be converted
@@ -422,8 +422,8 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
        __u32 clc_len;  /* calculated length */
        cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len));
 
-       if (length < 2 + sizeof (struct smb_hdr)) {
-               if ((length >= sizeof (struct smb_hdr) - 1)
+       if (length < 2 + sizeof(struct smb_hdr)) {
+               if ((length >= sizeof(struct smb_hdr) - 1)
                            && (smb->Status.CifsError != 0)) {
                        smb->WordCount = 0;
                        /* some error cases do not return wct and bcc */
index f06359cb22ee96645e7dfd7b0aa62cc0de216b2b..646e1f06941b5c8062e9c8e590c2e2790736ab7f 100644 (file)
@@ -132,6 +132,34 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
        {0, 0}
 };
 
+
+/* if the mount helper is missing we need to reverse the 1st slash
+   from '/' to backslash in order to format the UNC properly for
+   ip address parsing and for tree connect (unless the user
+   remembered to put the UNC name in properly). Fortunately we do
+   not have to call this twice (we check for IPv4 addresses
+   first, so it is already converted by the time we
+   try IPv6 addresses */
+static int canonicalize_unc(char *cp)
+{
+       int i;
+
+       for (i = 0; i <= 46 /* INET6_ADDRSTRLEN */ ; i++) {
+               if (cp[i] == 0)
+                       break;
+               if (cp[i] == '\\')
+                       break;
+               if (cp[i] == '/') {
+#ifdef CONFIG_CIFS_DEBUG2
+                       cFYI(1, ("change slash to backslash in malformed UNC"));
+#endif
+                       cp[i] = '\\';
+                       return 1;
+               }
+       }
+       return 0;
+}
+
 /* Convert string containing dotted ip address to binary form */
 /* returns 0 if invalid address */
 
@@ -141,11 +169,13 @@ cifs_inet_pton(int address_family, char *cp, void *dst)
        int ret = 0;
 
        /* calculate length by finding first slash or NULL */
-       /* BB Should we convert '/' slash to '\' here since it seems already
-        * done before this */
-       if ( address_family == AF_INET ) {
-               ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL);
-       } else if ( address_family == AF_INET6 ) {
+       if (address_family == AF_INET) {
+               ret = in4_pton(cp, -1 /* len */, dst, '\\', NULL);
+               if (ret == 0) {
+                       if (canonicalize_unc(cp))
+                               ret = in4_pton(cp, -1, dst, '\\', NULL);
+               }
+       } else if (address_family == AF_INET6) {
                ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL);
        }
 #ifdef CONFIG_CIFS_DEBUG2
@@ -740,7 +770,7 @@ cifs_print_status(__u32 status_code)
 
 
 static void
-ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
+ntstatus_to_dos(__u32 ntstatus, __u8 *eclass, __u16 *ecode)
 {
        int i;
        if (ntstatus == 0) {
@@ -793,8 +823,8 @@ map_smb_to_linux_error(struct smb_hdr *smb, int logErr)
        if (smberrclass == ERRDOS) {  /* 1 byte field no need to byte reverse */
                for (i = 0;
                     i <
-                    sizeof (mapping_table_ERRDOS) /
-                    sizeof (struct smb_to_posix_error); i++) {
+                    sizeof(mapping_table_ERRDOS) /
+                    sizeof(struct smb_to_posix_error); i++) {
                        if (mapping_table_ERRDOS[i].smb_err == 0)
                                break;
                        else if (mapping_table_ERRDOS[i].smb_err ==
@@ -807,8 +837,8 @@ map_smb_to_linux_error(struct smb_hdr *smb, int logErr)
        } else if (smberrclass == ERRSRV) {   /* server class of error codes */
                for (i = 0;
                     i <
-                    sizeof (mapping_table_ERRSRV) /
-                    sizeof (struct smb_to_posix_error); i++) {
+                    sizeof(mapping_table_ERRSRV) /
+                    sizeof(struct smb_to_posix_error); i++) {
                        if (mapping_table_ERRSRV[i].smb_err == 0)
                                break;
                        else if (mapping_table_ERRSRV[i].smb_err ==
@@ -837,14 +867,14 @@ map_smb_to_linux_error(struct smb_hdr *smb, int logErr)
 unsigned int
 smbCalcSize(struct smb_hdr *ptr)
 {
-       return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
+       return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) +
                2 /* size of the bcc field */ + BCC(ptr));
 }
 
 unsigned int
 smbCalcSize_LE(struct smb_hdr *ptr)
 {
-       return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
+       return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) +
                2 /* size of the bcc field */ + le16_to_cpu(BCC_LE(ptr)));
 }
 
index 3746580e97016f390a491684ecfae3a14cbd5796..0f22def4bdff47e30300dec9bcad5be12cd193d6 100644 (file)
@@ -171,7 +171,13 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
        /* Linux can not store file creation time unfortunately so ignore it */
 
        cifsInfo->cifsAttrs = attr;
-       cifsInfo->time = jiffies;
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
+               /* get more accurate mode via ACL - so force inode refresh */
+               cifsInfo->time = 0;
+       } else
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
+               cifsInfo->time = jiffies;
 
        /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
        /* 2767 perms - indicate mandatory locking */
@@ -495,7 +501,7 @@ ffirst_retry:
 static int cifs_unicode_bytelen(char *str)
 {
        int len;
-       __le16 * ustr = (__le16 *)str;
+       __le16 *ustr = (__le16 *)str;
 
        for (len = 0; len <= PATH_MAX; len++) {
                if (ustr[len] == 0)
index 90542a39be1750197345b404bf23806c400c8460..58bbfd992cc0f4afe26f057752aeddfbd3da53ba 100644 (file)
@@ -80,7 +80,7 @@ SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
 
 /* Routines for Windows NT MD4 Hash functions. */
 static int
-_my_wcslen(__u16 * str)
+_my_wcslen(__u16 *str)
 {
        int len = 0;
        while (*str++ != 0)
@@ -96,7 +96,7 @@ _my_wcslen(__u16 * str)
  */
 
 static int
-_my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
+_my_mbstowcs(__u16 *dst, const unsigned char *src, int len)
 {      /* BB not a very good conversion routine - change/fix */
        int i;
        __u16 val;
@@ -125,9 +125,9 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16)
        /* Password cannot be longer than 128 characters */
        if (passwd) {
                len = strlen((char *) passwd);
-               if (len > 128) {
+               if (len > 128)
                        len = 128;
-               }
+
                /* Password must be converted to NT unicode */
                _my_mbstowcs(wpwd, passwd, len);
        } else
@@ -135,7 +135,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16)
 
        wpwd[len] = 0;  /* Ensure string is null terminated */
        /* Calculate length in bytes */
-       len = _my_wcslen(wpwd) * sizeof (__u16);
+       len = _my_wcslen(wpwd) * sizeof(__u16);
 
        mdfour(p16, (unsigned char *) wpwd, len);
        memset(wpwd, 0, 129 * 2);
@@ -167,7 +167,7 @@ nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16])
        E_P16((unsigned char *) passwd, (unsigned char *) p16);
 
        /* clear out local copy of user's password (just being paranoid). */
-       memset(passwd, '\0', sizeof (passwd));
+       memset(passwd, '\0', sizeof(passwd));
 }
 #endif
 
@@ -189,8 +189,10 @@ ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
                return;
        dom_u = user_u + 1024;
 
-       /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
-          push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
+       /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2,
+                       STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
+          push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2,
+                       STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
 
        /* BB user and domain may need to be uppercased */
        user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage);
index 369e838bebd3142554b72d58e7333547079b3e41..54e8ef96cb7930c07734aa9f0b808eaa2e215953 100644 (file)
@@ -265,7 +265,9 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
                else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
                        __u16 fid;
                        int oplock = FALSE;
-                       if (experimEnabled) 
+                       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,
@@ -273,10 +275,9 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
                        /* else rc is EOPNOTSUPP from above */
 
-                       if(rc == 0) {
-                               rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
-                                       ea_value, buf_size,
-                                       ACL_TYPE_ACCESS);
+                       if (rc == 0) {
+                               rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, &pacl,
+                                                     &buflen);
                                CIFSSMBClose(xid, pTcon, fid);
                        }
                }
index 2c942e2d14ea2b3ebf2fb51bcf692e3a37565ae5..4ccaaa4b13b229ec17456789ead9aad76c8078bf 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1692,7 +1692,10 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
        if (!binfmt || !binfmt->core_dump)
                goto fail;
        down_write(&mm->mmap_sem);
-       if (!get_dumpable(mm)) {
+       /*
+        * If another thread got here first, or we are not dumpable, bail out.
+        */
+       if (mm->core_waiters || !get_dumpable(mm)) {
                up_write(&mm->mmap_sem);
                goto fail;
        }
@@ -1706,7 +1709,6 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
                flag = O_EXCL;          /* Stop rewrite attacks */
                current->fsuid = 0;     /* Dump root private */
        }
-       set_dumpable(mm, 0);
 
        retval = coredump_wait(exit_code);
        if (retval < 0)
index 0217b74cc9fc0cd30456d40929e6196229680178..3a4ffba3d6bcf2c30bbad9e6cd7f87cce8a165ba 100644 (file)
@@ -203,6 +203,11 @@ static inline void save_init_fpu(struct task_struct *tsk)
  */
 static inline int restore_i387(struct _fpstate __user *buf)
 {
+       set_used_math();
+       if (!(task_thread_info(current)->status & TS_USEDFPU)) {
+               clts();
+               task_thread_info(current)->status |= TS_USEDFPU;
+       }
        return restore_fpu_checking((__force struct i387_fxsave_struct *)buf);
 }
 
index 84f59fde1a10d83a78c4cfca6d08f5705da5021e..9acb413858ac532e9a668d4d2b351f4acdbd14c3 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1080,7 +1080,6 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
        struct page *page;
        struct kmem_cache_node *n;
        void *start;
-       void *end;
        void *last;
        void *p;
 
@@ -1101,7 +1100,6 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
                SetSlabDebug(page);
 
        start = page_address(page);
-       end = start + s->objects * s->size;
 
        if (unlikely(s->flags & SLAB_POISON))
                memset(start, POISON_INUSE, PAGE_SIZE << s->order);